! ! $Id: startvar.F 1299 2010-01-20 14:27:21Z snguyen $ ! MODULE startvar #ifdef CPP_EARTH ! This module is designed to work for Earth (and with ioipsl) ! ! ! There are three ways to access data from the database of atmospheric data which ! can be used to initialize the model. This depends on the type of field which needs ! to be extracted. ! We will details the possible arguments to startget here : ! ! - A 2D variable on the dynamical grid : ! CALL startget_phys2d(varname, iml, jml, lon_in, lat_in, champ, val_ex, jml2, lon_in2, lat_in2, interbar ) ! ! - A 1D variable on the physical grid : ! CALL startget_phys1d(varname, iml, jml, lon_in, lat_in, nbindex, champ, val_exp, jml2, lon_in2, lat_in2, interbar ) ! ! ! - A 3D variable on the dynamical grid : ! CALL startget_dyn(varname, iml, jml, lon_in, lat_in, lml, pls, workvar, champ, val_exp, jml2, lon_in2, lat_in2, interbar ) ! ! ! There is special constraint on the atmospheric data base except that the ! the data needs to be in netCDF and the variables should have the the following ! names in the file : ! ! 'RELIEF' : High resolution orography ! 'ST' : Surface temperature ! 'CDSW' : Soil moisture ! 'Z' : Surface geopotential ! 'SP' : Surface pressure ! 'U' : East ward wind ! 'V' : Northward wind ! 'TEMP' : Temperature ! 'R' : Relative humidity ! USE ioipsl ! ! IMPLICIT NONE ! ! PRIVATE public startget_phys2d, startget_phys1d, startget_dyn ! INTEGER, SAVE :: fid_phys, fid_dyn INTEGER, SAVE :: iml_phys, iml_rel, iml_dyn INTEGER, SAVE :: jml_phys, jml_rel, jml_dyn INTEGER, SAVE :: llm_dyn, ttm_dyn REAL, ALLOCATABLE, SAVE, DIMENSION (:,:) :: lon_phys, lon_rug, . lon_alb, lon_rel, lon_dyn REAL, ALLOCATABLE, SAVE, DIMENSION (:,:) :: lat_phys, lat_rug, . lat_alb, lat_rel, lat_dyn REAL, ALLOCATABLE, SAVE, DIMENSION (:) :: levdyn_ini REAL, ALLOCATABLE, SAVE, DIMENSION (:,:) :: relief, zstd, zsig, . zgam, zthe, zpic, zval REAL, ALLOCATABLE, SAVE, DIMENSION (:,:) :: rugo, masque, phis ! REAL, ALLOCATABLE, SAVE, DIMENSION (:,:) :: tsol, qsol, psol_dyn REAL, ALLOCATABLE, SAVE, DIMENSION (:,:,:) :: var_ana3d ! CONTAINS ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! SUBROUTINE startget_phys2d(varname, iml, jml, lon_in, lat_in, . champ, val_exp, jml2, lon_in2, lat_in2 , interbar, masque_lu ) ! ! There is a big mess with the size in logitude, should it be iml or iml+1. ! I have chosen to use the iml+1 as an argument to this routine and we declare ! internaly smaler fields when needed. This needs to be cleared once and for all in LMDZ. ! A convention is required. ! ! CHARACTER*(*), INTENT(in) :: varname INTEGER, INTENT(in) :: iml, jml ,jml2 REAL, INTENT(in) :: lon_in(iml), lat_in(jml) REAL, INTENT(in) :: lon_in2(iml), lat_in2(jml2) REAL, INTENT(inout) :: champ(iml,jml) REAL, INTENT(in) :: val_exp REAL, INTENT(in), optional :: masque_lu(iml,jml) LOGICAL interbar ! ! This routine only works if the variable does not exist or is constant ! IF ( MINVAL(champ(:,:)).EQ.MAXVAL(champ(:,:)) .AND. .MINVAL(champ(:,:)).EQ.val_exp ) THEN ! SELECTCASE(varname) ! CASE ('relief') ! ! If we do not have the orography we need to get it ! IF ( .NOT.ALLOCATED(relief)) THEN ! if (present(masque_lu)) then CALL start_init_orog( iml, jml, lon_in, lat_in, . jml2,lon_in2,lat_in2, interbar, masque_lu ) else CALL start_init_orog( iml, jml, lon_in, lat_in, . jml2,lon_in2,lat_in2, interbar) endif ! ENDIF ! IF (SIZE(relief) .NE. SIZE(champ)) THEN ! WRITE(*,*) 'STARTVAR module has been', .' initialized to the wrong size' STOP ! ENDIF ! champ(:,:) = relief(:,:) ! CASE ('rugosite') ! ! If we do not have the orography we need to get it ! IF ( .NOT.ALLOCATED(rugo)) THEN ! CALL start_init_orog( iml, jml, lon_in, lat_in, . jml2,lon_in2,lat_in2 , interbar ) ! ENDIF ! IF (SIZE(rugo) .NE. SIZE(champ)) THEN ! WRITE(*,*) . 'STARTVAR module has been initialized to the wrong size' STOP ! ENDIF ! champ(:,:) = rugo(:,:) ! CASE ('masque') ! ! If we do not have the orography we need to get it ! IF ( .NOT.ALLOCATED(masque)) THEN ! CALL start_init_orog( iml, jml, lon_in, lat_in, . jml2,lon_in2,lat_in2 , interbar ) ! ENDIF ! IF (SIZE(masque) .NE. SIZE(champ)) THEN ! WRITE(*,*) . 'STARTVAR module has been initialized to the wrong size' STOP ! ENDIF ! champ(:,:) = masque(:,:) ! CASE ('surfgeo') ! ! If we do not have the orography we need to get it ! IF ( .NOT.ALLOCATED(phis)) THEN ! CALL start_init_orog( iml, jml, lon_in, lat_in, . jml2,lon_in2, lat_in2 , interbar ) ! ENDIF ! IF (SIZE(phis) .NE. SIZE(champ)) THEN ! WRITE(*,*) . 'STARTVAR module has been initialized to the wrong size' STOP ! ENDIF ! champ(:,:) = phis(:,:) ! CASE ('psol') ! ! If we do not have the orography we need to get it ! IF ( .NOT.ALLOCATED(psol_dyn)) THEN ! CALL start_init_dyn( iml, jml, lon_in, lat_in, . jml2,lon_in2, lat_in2 , interbar ) ! ENDIF ! IF (SIZE(psol_dyn) .NE. SIZE(champ)) THEN ! WRITE(*,*) . 'STARTVAR module has been initialized to the wrong size' STOP ! ENDIF ! champ(:,:) = psol_dyn(:,:) ! CASE DEFAULT ! WRITE(*,*) 'startget_phys2d' WRITE(*,*) 'No rule is present to extract variable', . varname(:LEN_TRIM(varname)),' from any data set' STOP ! END SELECT ! ELSE ! ! There are a few fields we might need if we need to interpolate 3D filed. Thus if they come through here we ! will catch them ! SELECTCASE(varname) ! CASE ('surfgeo') ! IF ( .NOT.ALLOCATED(phis)) THEN ALLOCATE(phis(iml,jml)) ENDIF ! IF (SIZE(phis) .NE. SIZE(champ)) THEN ! WRITE(*,*) . 'STARTVAR module has been initialized to the wrong size' STOP ! ENDIF ! phis(:,:) = champ(:,:) ! END SELECT ! ENDIF ! END SUBROUTINE startget_phys2d ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! SUBROUTINE start_init_orog ( iml,jml,lon_in, lat_in,jml2,lon_in2 , , lat_in2 , interbar, masque_lu ) ! INTEGER, INTENT(in) :: iml, jml, jml2 REAL, INTENT(in) :: lon_in(iml), lat_in(jml) REAL, INTENT(in) :: lon_in2(iml), lat_in2(jml2) REAL, intent(in), optional :: masque_lu(iml,jml) LOGICAL interbar ! ! LOCAL ! LOGICAL interbar2 REAL :: lev(1), date, dt,chmin,chmax INTEGER :: itau(1), fid INTEGER :: llm_tmp, ttm_tmp INTEGER :: i, j INTEGER :: iret CHARACTER*25 title REAL, ALLOCATABLE :: relief_hi(:,:) REAL, ALLOCATABLE :: lon_rad(:), lat_rad(:) REAL, ALLOCATABLE :: lon_ini(:), lat_ini(:) REAL, ALLOCATABLE :: tmp_var(:,:) INTEGER, ALLOCATABLE :: tmp_int(:,:) ! CHARACTER*120 :: orogfname LOGICAL :: check=.TRUE. ! ! orogfname = 'Relief.nc' ! IF ( check ) WRITE(*,*) 'Reading the high resolution orography' ! CALL flininfo(orogfname,iml_rel, jml_rel, llm_tmp, ttm_tmp, fid) ! ALLOCATE (lat_rel(iml_rel,jml_rel), stat=iret) ALLOCATE (lon_rel(iml_rel,jml_rel), stat=iret) ALLOCATE (relief_hi(iml_rel,jml_rel), stat=iret) ! CALL flinopen(orogfname, .FALSE., iml_rel, jml_rel, .llm_tmp, lon_rel, lat_rel, lev, ttm_tmp, . itau, date, dt, fid) ! CALL flinget(fid, 'RELIEF', iml_rel, jml_rel, llm_tmp, . ttm_tmp, 1, 1, relief_hi) ! CALL flinclo(fid) ! ! In case we have a file which is in degrees we do the transformation ! ALLOCATE(lon_rad(iml_rel)) ALLOCATE(lon_ini(iml_rel)) IF ( MAXVAL(lon_rel(:,:)) .GT. 2.0 * ASIN(1.0) ) THEN lon_ini(:) = lon_rel(:,1) * 2.0 * ASIN(1.0) / 180.0 ELSE lon_ini(:) = lon_rel(:,1) ENDIF ALLOCATE(lat_rad(jml_rel)) ALLOCATE(lat_ini(jml_rel)) IF ( MAXVAL(lat_rel(:,:)) .GT. 2.0 * ASIN(1.0) ) THEN lat_ini(:) = lat_rel(1,:) * 2.0 * ASIN(1.0) / 180.0 ELSE lat_ini(:) = lat_rel(1,:) ENDIF ! ! title='RELIEF' interbar2 = .FALSE. CALL conf_dat2d(title,iml_rel, jml_rel, lon_ini, lat_ini, . lon_rad, lat_rad, relief_hi , interbar2 ) IF ( check ) WRITE(*,*) 'Computes all the parameters needed', .' for the gravity wave drag code' ! ! Allocate the data we need to put in the interpolated fields ! ! RELIEF: orographie moyenne ALLOCATE(relief(iml,jml)) ! zphi : orographie moyenne ALLOCATE(phis(iml,jml)) ! zstd: deviation standard de l'orographie sous-maille ALLOCATE(zstd(iml,jml)) ! zsig: pente de l'orographie sous-maille ALLOCATE(zsig(iml,jml)) ! zgam: anisotropy de l'orographie sous maille ALLOCATE(zgam(iml,jml)) ! zthe: orientation de l'axe oriente dans la direction ! de plus grande pente de l'orographie sous maille ALLOCATE(zthe(iml,jml)) ! zpic: hauteur pics de la SSO ALLOCATE(zpic(iml,jml)) ! zval: hauteur vallees de la SSO ALLOCATE(zval(iml,jml)) ! masque : Masque terre ocean ALLOCATE(tmp_int(iml,jml)) ALLOCATE(masque(iml,jml)) masque = -99999. if (present(masque_lu)) then masque = masque_lu endif ! CALL grid_noro(iml_rel, jml_rel, lon_rad, lat_rad, relief_hi, . iml-1, jml, lon_in, lat_in, . phis, relief, zstd, zsig, zgam, zthe, zpic, zval, masque) phis = phis * 9.81 ! ! masque(:,:) = REAL(tmp_int(:,:)) ! ! Compute surface roughness ! IF ( check ) WRITE(*,*) .'Compute surface roughness induced by the orography' ! ALLOCATE(rugo(iml,jml)) ALLOCATE(tmp_var(iml-1,jml)) ! CALL rugsoro(iml_rel, jml_rel, lon_rad, lat_rad, relief_hi, . iml-1, jml, lon_in, lat_in, tmp_var) ! DO j = 1, jml DO i = 1, iml-1 rugo(i,j) = tmp_var(i,j) ENDDO rugo(iml,j) = tmp_var(1,j) ENDDO c cc *** rugo n'est pas utilise pour l'instant ****** ! ! Build land-sea mask ! ! RETURN ! END SUBROUTINE start_init_orog ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! SUBROUTINE startget_phys1d(varname, iml, jml, lon_in, .lat_in, nbindex, champ, val_exp ,jml2, lon_in2, lat_in2,interbar) ! CHARACTER*(*), INTENT(in) :: varname INTEGER, INTENT(in) :: iml, jml, nbindex, jml2 REAL, INTENT(in) :: lon_in(iml), lat_in(jml) REAL, INTENT(in) :: lon_in2(iml), lat_in2(jml2) REAL, INTENT(inout) :: champ(nbindex) REAL, INTENT(in) :: val_exp LOGICAL interbar ! ! ! This routine only works if the variable does not exist or is constant ! IF ( MINVAL(champ(:)).EQ.MAXVAL(champ(:)) .AND. .MINVAL(champ(:)).EQ.val_exp ) THEN SELECTCASE(varname) CASE ('tsol') IF ( .NOT.ALLOCATED(tsol)) THEN CALL start_init_phys( iml, jml, lon_in, lat_in, . jml2, lon_in2, lat_in2, interbar ) ENDIF IF ( SIZE(tsol) .NE. SIZE(lon_in)*SIZE(lat_in) ) THEN WRITE(*,*) . 'STARTVAR module has been initialized to the wrong size' STOP ENDIF CALL gr_dyn_fi(1, iml, jml, nbindex, tsol, champ) CASE ('qsol') IF ( .NOT.ALLOCATED(qsol)) THEN CALL start_init_phys( iml, jml, lon_in, lat_in, . jml2, lon_in2,lat_in2 , interbar ) ENDIF IF ( SIZE(qsol) .NE. SIZE(lon_in)*SIZE(lat_in) ) THEN WRITE(*,*) . 'STARTVAR module has been initialized to the wrong size' STOP ENDIF CALL gr_dyn_fi(1, iml, jml, nbindex, qsol, champ) CASE ('psol') IF ( .NOT.ALLOCATED(psol_dyn)) THEN CALL start_init_dyn( iml, jml, lon_in, lat_in, . jml2, lon_in2,lat_in2 , interbar ) ENDIF IF (SIZE(psol_dyn) .NE. SIZE(lon_in)*SIZE(lat_in)) THEN WRITE(*,*) . 'STARTVAR module has been initialized to the wrong size' STOP ENDIF CALL gr_dyn_fi(1, iml, jml, nbindex, psol_dyn, champ) CASE ('zmea') IF ( .NOT.ALLOCATED(relief)) THEN CALL start_init_orog( iml, jml, lon_in, lat_in, . jml2, lon_in2,lat_in2 , interbar ) ENDIF IF ( SIZE(relief) .NE. SIZE(lon_in)*SIZE(lat_in) ) THEN WRITE(*,*) . 'STARTVAR module has been initialized to the wrong size' STOP ENDIF CALL gr_dyn_fi(1, iml, jml, nbindex, relief, champ) CASE ('zstd') IF ( .NOT.ALLOCATED(zstd)) THEN CALL start_init_orog( iml, jml, lon_in, lat_in, . jml2, lon_in2,lat_in2 , interbar ) ENDIF IF ( SIZE(zstd) .NE. SIZE(lon_in)*SIZE(lat_in) ) THEN WRITE(*,*) . 'STARTVAR module has been initialized to the wrong size' STOP ENDIF CALL gr_dyn_fi(1, iml, jml, nbindex,zstd, champ) CASE ('zsig') IF ( .NOT.ALLOCATED(zsig)) THEN CALL start_init_orog( iml, jml, lon_in, lat_in, . jml2, lon_in2,lat_in2 , interbar ) ENDIF IF ( SIZE(zsig) .NE. SIZE(lon_in)*SIZE(lat_in) ) THEN WRITE(*,*) . 'STARTVAR module has been initialized to the wrong size' STOP ENDIF CALL gr_dyn_fi(1, iml, jml, nbindex,zsig, champ) CASE ('zgam') IF ( .NOT.ALLOCATED(zgam)) THEN CALL start_init_orog( iml, jml, lon_in, lat_in, . jml2, lon_in2,lat_in2 , interbar ) ENDIF IF ( SIZE(zgam) .NE. SIZE(lon_in)*SIZE(lat_in) ) THEN WRITE(*,*) . 'STARTVAR module has been initialized to the wrong size' STOP ENDIF CALL gr_dyn_fi(1, iml, jml, nbindex,zgam, champ) CASE ('zthe') IF ( .NOT.ALLOCATED(zthe)) THEN CALL start_init_orog( iml, jml, lon_in, lat_in, . jml2, lon_in2,lat_in2 , interbar ) ENDIF IF ( SIZE(zthe) .NE. SIZE(lon_in)*SIZE(lat_in) ) THEN WRITE(*,*) . 'STARTVAR module has been initialized to the wrong size' STOP ENDIF CALL gr_dyn_fi(1, iml, jml, nbindex,zthe, champ) CASE ('zpic') IF ( .NOT.ALLOCATED(zpic)) THEN CALL start_init_orog( iml, jml, lon_in, lat_in, . jml2, lon_in2,lat_in2 , interbar ) ENDIF IF ( SIZE(zpic) .NE. SIZE(lon_in)*SIZE(lat_in) ) THEN WRITE(*,*) . 'STARTVAR module has been initialized to the wrong size' STOP ENDIF CALL gr_dyn_fi(1, iml, jml, nbindex,zpic, champ) CASE ('zval') IF ( .NOT.ALLOCATED(zval)) THEN CALL start_init_orog( iml, jml, lon_in, lat_in, . jml2, lon_in2,lat_in2 , interbar ) ENDIF IF ( SIZE(zval) .NE. SIZE(lon_in)*SIZE(lat_in) ) THEN WRITE(*,*) . 'STARTVAR module has been initialized to the wrong size' STOP ENDIF CALL gr_dyn_fi(1, iml, jml, nbindex,zval, champ) CASE ('rads') champ(:) = 0.0 CASE ('snow') champ(:) = 0.0 cIM "slab" ocean CASE ('tslab') champ(:) = 0.0 CASE ('seaice') champ(:) = 0.0 CASE ('rugmer') champ(:) = 0.001 CASE ('agsno') champ(:) = 50.0 CASE DEFAULT WRITE(*,*) 'startget_phys1d' WRITE(*,*) 'No rule is present to extract variable ', . varname(:LEN_TRIM(varname)),' from any data set' STOP END SELECT ELSE ! ! If we see tsol we catch it as we may need it for a 3D interpolation ! SELECTCASE(varname) CASE ('tsol') IF ( .NOT.ALLOCATED(tsol)) THEN ALLOCATE(tsol(SIZE(lon_in),SIZE(lat_in) )) ENDIF CALL gr_fi_dyn(1, iml, jml, nbindex, champ, tsol) END SELECT ENDIF END SUBROUTINE startget_phys1d !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! SUBROUTINE start_init_phys( iml, jml, lon_in, lat_in, jml2, . lon_in2, lat_in2 , interbar ) use inter_barxy_m, only: inter_barxy ! INTEGER, INTENT(in) :: iml, jml ,jml2 REAL, INTENT(in) :: lon_in(iml), lat_in(jml) REAL, INTENT(in) :: lon_in2(iml), lat_in2(jml2) LOGICAL interbar ! ! LOCAL ! !ac REAL :: lev(1), date, dt REAL :: date, dt REAL, DIMENSION(:), ALLOCATABLE :: levphys_ini !ac INTEGER :: itau(1) INTEGER :: llm_tmp, ttm_tmp INTEGER :: i, j ! CHARACTER*25 title CHARACTER*120 :: physfname LOGICAL :: check=.TRUE. ! REAL, ALLOCATABLE :: lon_rad(:), lat_rad(:) REAL, ALLOCATABLE :: lon_ini(:), lat_ini(:) REAL, ALLOCATABLE :: var_ana(:,:), tmp_var(:,:) ! physfname = 'ECPHY.nc' ! IF ( check ) WRITE(*,*) 'Opening the surface analysis' ! CALL flininfo(physfname, iml_phys, jml_phys, llm_tmp, . ttm_tmp, fid_phys) ! ALLOCATE (lat_phys(iml_phys,jml_phys)) ALLOCATE (lon_phys(iml_phys,jml_phys)) !ac ALLOCATE (levphys_ini(llm_tmp)) ! ! CALL flinopen(physfname, .FALSE., iml_phys, jml_phys, ! . llm_tmp, lon_phys, lat_phys, lev, ttm_tmp, ! . itau, date, dt, fid_phys) ! CALL flinopen(physfname, .FALSE., iml_phys, jml_phys, . llm_tmp, lon_phys, lat_phys, levphys_ini, ttm_tmp, . itau, date, dt, fid_phys) ! DEALLOCATE (levphys_ini) !ac ! ! Allocate the space we will need to get the data out of this file ! ALLOCATE(var_ana(iml_phys, jml_phys)) ! ! In case we have a file which is in degrees we do the transformation ! ALLOCATE(lon_rad(iml_phys)) ALLOCATE(lon_ini(iml_phys)) IF ( MAXVAL(lon_phys(:,:)) .GT. 2.0 * ASIN(1.0) ) THEN lon_ini(:) = lon_phys(:,1) * 2.0 * ASIN(1.0) / 180.0 ELSE lon_ini(:) = lon_phys(:,1) ENDIF ALLOCATE(lat_rad(jml_phys)) ALLOCATE(lat_ini(jml_phys)) IF ( MAXVAL(lat_phys(:,:)) .GT. 2.0 * ASIN(1.0) ) THEN lat_ini(:) = lat_phys(1,:) * 2.0 * ASIN(1.0) / 180.0 ELSE lat_ini(:) = lat_phys(1,:) ENDIF ! ! We get the two standard varibales ! Surface temperature ! ALLOCATE(tsol(iml,jml)) ALLOCATE(tmp_var(iml-1,jml)) ! ! CALL flinget(fid_phys, 'ST', iml_phys, jml_phys, .llm_tmp, ttm_tmp, 1, 1, var_ana) title='ST' CALL conf_dat2d(title,iml_phys, jml_phys, lon_ini, lat_ini, . lon_rad, lat_rad, var_ana , interbar ) IF ( interbar ) THEN WRITE(6,*) '-------------------------------------------------', ,'--------------' WRITE(6,*) '$$$ Utilisation de l interpolation barycentrique ', , ' pour ST $$$ ' WRITE(6,*) '-------------------------------------------------', ,'--------------' CALL inter_barxy(lon_rad, lat_rad(:jml_phys -1), var_ana, $ lon_in2(:iml-1), lat_in2(:jml-1), tmp_var) ELSE CALL grille_m(iml_phys, jml_phys, lon_rad, lat_rad, . var_ana, iml-1, jml, lon_in, lat_in, tmp_var ) ENDIF CALL gr_int_dyn(tmp_var, tsol, iml-1, jml) ! ! Soil moisture ! ALLOCATE(qsol(iml,jml)) CALL flinget(fid_phys, 'CDSW', iml_phys, jml_phys, . llm_tmp, ttm_tmp, 1, 1, var_ana) title='CDSW' CALL conf_dat2d(title,iml_phys, jml_phys, lon_ini, lat_ini, . lon_rad, lat_rad, var_ana, interbar ) IF ( interbar ) THEN WRITE(6,*) '-------------------------------------------------', ,'--------------' WRITE(6,*) '$$$ Utilisation de l interpolation barycentrique ', , ' pour CDSW $$$ ' WRITE(6,*) '-------------------------------------------------', ,'--------------' CALL inter_barxy(lon_rad, lat_rad(:jml_phys -1), var_ana, $ lon_in2(:iml-1), lat_in2(:jml-1), tmp_var) ELSE CALL grille_m(iml_phys, jml_phys, lon_rad, lat_rad, . var_ana, iml-1, jml, lon_in, lat_in, tmp_var ) ENDIF c CALL gr_int_dyn(tmp_var, qsol, iml-1, jml) ! CALL flinclo(fid_phys) ! END SUBROUTINE start_init_phys ! ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ! SUBROUTINE startget_dyn(varname, lon_in, lat_in, . pls, workvar, champ, val_exp, lon_in2, lat_in2 , , interbar ) use assert_eq_m, only: assert_eq ! ! ARGUMENTS ! CHARACTER(len=*), INTENT(in) :: varname REAL, INTENT(in) :: lon_in(:) ! dim(iml) REAL, INTENT(in) :: lat_in(:) ! dim(jml) REAL, INTENT(in) :: lon_in2(:) ! dim(iml) REAL, INTENT(in) :: lat_in2(:) ! dim(jml2) REAL, INTENT(in) :: pls(:, :, :) ! dim(iml, jml, lml) REAL, INTENT(in) :: workvar(:, :, :) ! dim(iml, jml, lml) REAL, INTENT(inout) :: champ(:, :, :) ! dim(iml, jml, lml) REAL, INTENT(in) :: val_exp LOGICAL interbar ! ! LOCAL ! INTEGER :: il, ij, ii, iml, jml, lml, jml2 REAL :: xppn, xpps ! #include "dimensions.h" #include "paramet.h" #include "comgeom2.h" #include "comconst.h" ! ! This routine only works if the variable does not exist or is constant ! C ----------------------------- iml = assert_eq((/size(lon_in), size(pls, 1), size(workvar, 1), $ size(champ, 1), size(lon_in2)/), "startget_dyn iml") jml = assert_eq(size(lat_in), size(pls, 2), size(workvar, 2), $ size(champ, 2), "startget_dyn jml") lml = assert_eq(size(pls, 3), size(workvar, 3), size(champ, 3), $ "startget_dyn lml") jml2 = size(lat_in2) IF ( MINVAL(champ(:,:,:)).EQ.MAXVAL(champ(:,:,:)) .AND. . MINVAL(champ(:,:,:)).EQ.val_exp ) THEN ! SELECTCASE(varname) CASE ('u') IF ( .NOT.ALLOCATED(psol_dyn)) THEN CALL start_init_dyn( iml, jml, lon_in, lat_in, jml2 , . lon_in2,lat_in2 , interbar ) ENDIF CALL start_inter_3d('U', iml, jml, lml, lon_in, . lat_in, jml2, lon_in2, lat_in2, pls, champ,interbar ) DO il=1,lml DO ij=1,jml DO ii=1,iml-1 champ(ii,ij,il) = champ(ii,ij,il) * cu(ii,ij) ENDDO champ(iml,ij, il) = champ(1,ij, il) ENDDO ENDDO CASE ('v') IF ( .NOT.ALLOCATED(psol_dyn)) THEN CALL start_init_dyn( iml, jml, lon_in, lat_in , jml2, . lon_in2, lat_in2 , interbar ) ENDIF CALL start_inter_3d('V', iml, jml, lml, lon_in, . lat_in, jml2, lon_in2, lat_in2, pls, champ, interbar ) DO il=1,lml DO ij=1,jml DO ii=1,iml-1 champ(ii,ij,il) = champ(ii,ij,il) * cv(ii,ij) ENDDO champ(iml,ij, il) = champ(1,ij, il) ENDDO ENDDO CASE ('t') IF ( .NOT.ALLOCATED(psol_dyn)) THEN CALL start_init_dyn( iml, jml, lon_in, lat_in, jml2 , . lon_in2, lat_in2 ,interbar ) ENDIF CALL start_inter_3d('TEMP', iml, jml, lml, lon_in, . lat_in, jml2, lon_in2, lat_in2, pls, champ, interbar ) CASE ('tpot') IF ( .NOT.ALLOCATED(psol_dyn)) THEN CALL start_init_dyn( iml, jml, lon_in, lat_in , jml2 , . lon_in2, lat_in2 , interbar ) ENDIF CALL start_inter_3d('TEMP', iml, jml, lml, lon_in, . lat_in, jml2, lon_in2, lat_in2, pls, champ, interbar ) IF ( MINVAL(workvar(:,:,:)) .NE. MAXVAL(workvar(:,:,:)) ) . THEN DO il=1,lml DO ij=1,jml DO ii=1,iml-1 champ(ii,ij,il) = champ(ii,ij,il) * cpp . / workvar(ii,ij,il) ENDDO champ(iml,ij,il) = champ(1,ij,il) ENDDO ENDDO DO il=1,lml xppn = SUM(aire(:,1)*champ(:,1,il))/apoln xpps = SUM(aire(:,jml)*champ(:,jml,il))/apols champ(:,1,il) = xppn champ(:,jml,il) = xpps ENDDO ELSE WRITE(*,*)'Could not compute potential temperature as the' WRITE(*,*)'Exner function is missing or constant.' STOP ENDIF CASE ('q') IF ( .NOT.ALLOCATED(psol_dyn)) THEN CALL start_init_dyn( iml, jml, lon_in, lat_in, jml2 , . lon_in2, lat_in2 , interbar ) ENDIF CALL start_inter_3d('R', iml, jml, lml, lon_in, lat_in, . jml2, lon_in2, lat_in2, pls, champ, interbar ) IF ( MINVAL(workvar(:,:,:)) .NE. MAXVAL(workvar(:,:,:)) ) . THEN DO il=1,lml DO ij=1,jml DO ii=1,iml-1 champ(ii,ij,il) = 0.01 * champ(ii,ij,il) * . workvar(ii,ij,il) ENDDO champ(iml,ij,il) = champ(1,ij,il) ENDDO ENDDO WHERE ( champ .LT. 0.) champ = 1.0E-10 DO il=1,lml xppn = SUM(aire(:,1)*champ(:,1,il))/apoln xpps = SUM(aire(:,jml)*champ(:,jml,il))/apols champ(:,1,il) = xppn champ(:,jml,il) = xpps ENDDO ELSE WRITE(*,*)'Could not compute specific humidity as the' WRITE(*,*)'saturated humidity is missing or constant.' STOP ENDIF CASE DEFAULT WRITE(*,*) 'startget_dyn' WRITE(*,*) 'No rule is present to extract variable ', . varname(:LEN_TRIM(varname)),' from any data set' STOP END SELECT ENDIF END SUBROUTINE startget_dyn ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! SUBROUTINE start_init_dyn( iml, jml, lon_in, lat_in,jml2,lon_in2 , , lat_in2 , interbar ) ! use inter_barxy_m, only: inter_barxy INTEGER, INTENT(in) :: iml, jml, jml2 REAL, INTENT(in) :: lon_in(iml), lat_in(jml) REAL, INTENT(in) :: lon_in2(iml), lat_in2(jml2) LOGICAL interbar ! ! LOCAL ! REAL :: lev(1), date, dt INTEGER :: itau(1) INTEGER :: i, j integer :: iret ! CHARACTER*120 :: physfname LOGICAL :: check=.TRUE. ! REAL, ALLOCATABLE :: lon_rad(:), lat_rad(:) REAL, ALLOCATABLE :: lon_ini(:), lat_ini(:) REAL, ALLOCATABLE :: var_ana(:,:), tmp_var(:,:), z(:,:) REAL, ALLOCATABLE :: xppn(:), xpps(:) LOGICAL :: allo ! ! #include "dimensions.h" #include "paramet.h" #include "comgeom2.h" CHARACTER*25 title ! physfname = 'ECDYN.nc' ! IF ( check ) WRITE(*,*) 'Opening the surface analysis' ! CALL flininfo(physfname, iml_dyn, jml_dyn, llm_dyn, . ttm_dyn, fid_dyn) IF ( check ) WRITE(*,*) 'Values read: ', iml_dyn, jml_dyn, . llm_dyn, ttm_dyn ! ALLOCATE (lat_dyn(iml_dyn,jml_dyn), stat=iret) ALLOCATE (lon_dyn(iml_dyn,jml_dyn), stat=iret) ALLOCATE (levdyn_ini(llm_dyn), stat=iret) ! CALL flinopen(physfname, .FALSE., iml_dyn, jml_dyn, llm_dyn, . lon_dyn, lat_dyn, levdyn_ini, ttm_dyn, . itau, date, dt, fid_dyn) ! allo = allocated (var_ana) if (allo) then DEALLOCATE(var_ana, stat=iret) endif ALLOCATE(var_ana(iml_dyn, jml_dyn), stat=iret) allo = allocated (lon_rad) if (allo) then DEALLOCATE(lon_rad, stat=iret) endif ALLOCATE(lon_rad(iml_dyn), stat=iret) ALLOCATE(lon_ini(iml_dyn)) IF ( MAXVAL(lon_dyn(:,:)) .GT. 2.0 * ASIN(1.0) ) THEN lon_ini(:) = lon_dyn(:,1) * 2.0 * ASIN(1.0) / 180.0 ELSE lon_ini(:) = lon_dyn(:,1) ENDIF ALLOCATE(lat_rad(jml_dyn)) ALLOCATE(lat_ini(jml_dyn)) IF ( MAXVAL(lat_dyn(:,:)) .GT. 2.0 * ASIN(1.0) ) THEN lat_ini(:) = lat_dyn(1,:) * 2.0 * ASIN(1.0) / 180.0 ELSE lat_ini(:) = lat_dyn(1,:) ENDIF ! ALLOCATE(z(iml, jml)) ALLOCATE(tmp_var(iml-1,jml)) ! CALL flinget(fid_dyn, 'Z', iml_dyn, jml_dyn, 0, ttm_dyn, . 1, 1, var_ana) c title='Z' CALL conf_dat2d( title,iml_dyn, jml_dyn,lon_ini, lat_ini, . lon_rad, lat_rad, var_ana, interbar ) c IF ( interbar ) THEN WRITE(6,*) '-------------------------------------------------', ,'--------------' WRITE(6,*) '$$$ Utilisation de l interpolation barycentrique ', , ' pour Z $$$ ' WRITE(6,*) '-------------------------------------------------', ,'--------------' CALL inter_barxy(lon_rad, lat_rad(:jml_dyn -1), var_ana, $ lon_in2(:iml-1), lat_in2(:jml-1), tmp_var) ELSE CALL grille_m(iml_dyn, jml_dyn , lon_rad, lat_rad, var_ana, . iml-1, jml, lon_in, lat_in, tmp_var) ENDIF CALL gr_int_dyn(tmp_var, z, iml-1, jml) ! ALLOCATE(psol_dyn(iml, jml)) ! CALL flinget(fid_dyn, 'SP', iml_dyn, jml_dyn, 0, ttm_dyn, . 1, 1, var_ana) title='SP' CALL conf_dat2d( title,iml_dyn, jml_dyn,lon_ini, lat_ini, . lon_rad, lat_rad, var_ana, interbar ) IF ( interbar ) THEN WRITE(6,*) '-------------------------------------------------', ,'--------------' WRITE(6,*) '$$$ Utilisation de l interpolation barycentrique ', , ' pour SP $$$ ' WRITE(6,*) '-------------------------------------------------', ,'--------------' CALL inter_barxy(lon_rad, lat_rad(:jml_dyn -1), var_ana, $ lon_in2(:iml-1), lat_in2(:jml-1), tmp_var) ELSE CALL grille_m(iml_dyn, jml_dyn , lon_rad, lat_rad, var_ana, . iml-1, jml, lon_in, lat_in, tmp_var ) ENDIF CALL gr_int_dyn(tmp_var, psol_dyn, iml-1, jml) ! IF ( .NOT.ALLOCATED(tsol)) THEN ! These variables may have been allocated by the need to ! create a start field for them or by the varibale ! coming out of the restart file. In case we dor have it we will initialize it. ! CALL start_init_phys( iml, jml, lon_in, lat_in,jml2,lon_in2, . lat_in2 , interbar ) ELSE IF ( SIZE(tsol) .NE. SIZE(psol_dyn) ) THEN WRITE(*,*) 'start_init_dyn :' WRITE(*,*) 'The temperature field we have does not ', . 'have the right size' STOP ENDIF ENDIF IF ( .NOT.ALLOCATED(phis)) THEN ! ! These variables may have been allocated by the need to create a start field for them or by the varibale ! coming out of the restart file. In case we dor have it we will initialize it. ! CALL start_init_orog( iml, jml, lon_in, lat_in, jml2, lon_in2 , . lat_in2 , interbar ) ! ELSE ! IF (SIZE(phis) .NE. SIZE(psol_dyn)) THEN ! WRITE(*,*) 'start_init_dyn :' WRITE(*,*) 'The orography field we have does not ', . ' have the right size' STOP ENDIF ! ENDIF ! ! PSOL is computed in Pascals ! ! DO j = 1, jml DO i = 1, iml-1 psol_dyn(i,j) = psol_dyn(i,j)*(1.0+(z(i,j)-phis(i,j)) . /287.0/tsol(i,j)) ENDDO psol_dyn(iml,j) = psol_dyn(1,j) ENDDO ! ! ALLOCATE(xppn(iml-1)) ALLOCATE(xpps(iml-1)) ! DO i = 1, iml-1 xppn(i) = aire( i,1) * psol_dyn( i,1) xpps(i) = aire( i,jml) * psol_dyn( i,jml) ENDDO ! DO i = 1, iml psol_dyn(i,1 ) = SUM(xppn)/apoln psol_dyn(i,jml) = SUM(xpps)/apols ENDDO ! RETURN ! END SUBROUTINE start_init_dyn ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! SUBROUTINE start_inter_3d(varname, iml, jml, lml, lon_in, . lat_in, jml2, lon_in2, lat_in2, pls_in, var3d, interbar ) ! ! This subroutine gets a variables from a 3D file and does the interpolations needed ! ! use inter_barxy_m, only: inter_barxy ! ARGUMENTS ! CHARACTER*(*) :: varname INTEGER :: iml, jml, lml, jml2 REAL :: lon_in(iml), lat_in(jml), pls_in(iml, jml, lml) REAL :: lon_in2(iml) , lat_in2(jml2) REAL :: var3d(iml, jml, lml) LOGICAL interbar real chmin,chmax ! ! LOCAL ! CHARACTER*25 title INTEGER :: ii, ij, il, jsort,i,j,l REAL :: bx, by REAL, ALLOCATABLE :: lon_rad(:), lat_rad(:) REAL, ALLOCATABLE :: lon_ini(:), lat_ini(:) , lev_dyn(:) REAL, ALLOCATABLE :: var_tmp2d(:,:), var_tmp3d(:,:,:) REAL, ALLOCATABLE :: ax(:), ay(:), yder(:) ! REAL, ALLOCATABLE :: varrr(:,:,:) INTEGER, ALLOCATABLE :: lind(:) ! LOGICAL :: check = .TRUE. ! IF ( .NOT. ALLOCATED(var_ana3d)) THEN ALLOCATE(var_ana3d(iml_dyn, jml_dyn, llm_dyn)) ENDIF ! ALLOCATE(varrr(iml_dyn, jml_dyn, llm_dyn)) ! ! IF ( check) WRITE(*,*) 'Going into flinget to extract the 3D ', . ' field.', fid_dyn IF ( check) WRITE(*,*) fid_dyn, varname, iml_dyn, jml_dyn, . llm_dyn,ttm_dyn ! CALL flinget(fid_dyn, varname, iml_dyn, jml_dyn, llm_dyn, . ttm_dyn, 1, 1, var_ana3d) ! IF ( check) WRITE(*,*) 'Allocating space for the interpolation', . iml, jml, llm_dyn ! ALLOCATE(lon_rad(iml_dyn)) ALLOCATE(lon_ini(iml_dyn)) IF ( MAXVAL(lon_dyn(:,:)) .GT. 2.0 * ASIN(1.0) ) THEN lon_ini(:) = lon_dyn(:,1) * 2.0 * ASIN(1.0) / 180.0 ELSE lon_ini(:) = lon_dyn(:,1) ENDIF ALLOCATE(lat_rad(jml_dyn)) ALLOCATE(lat_ini(jml_dyn)) ALLOCATE(lev_dyn(llm_dyn)) IF ( MAXVAL(lat_dyn(:,:)) .GT. 2.0 * ASIN(1.0) ) THEN lat_ini(:) = lat_dyn(1,:) * 2.0 * ASIN(1.0) / 180.0 ELSE lat_ini(:) = lat_dyn(1,:) ENDIF ! CALL conf_dat3d ( varname,iml_dyn, jml_dyn, llm_dyn, lon_ini, . lat_ini, levdyn_ini, lon_rad, lat_rad, lev_dyn, var_ana3d , , interbar ) ALLOCATE(var_tmp2d(iml-1, jml)) ALLOCATE(var_tmp3d(iml, jml, llm_dyn)) ALLOCATE(ax(llm_dyn)) ALLOCATE(ay(llm_dyn)) ALLOCATE(yder(llm_dyn)) ALLOCATE(lind(llm_dyn)) ! DO il=1,llm_dyn ! IF( interbar ) THEN IF( il.EQ.1 ) THEN WRITE(6,*) '-------------------------------------------------', ,'--------------' WRITE(6,*) '$$$ Utilisation de l interpolation barycentrique ', , ' pour ', varname WRITE(6,*) '-------------------------------------------------', ,'--------------' ENDIF CALL inter_barxy(lon_rad, lat_rad(:jml_dyn -1), $ var_ana3d(:,:,il), lon_in2(:iml-1), lat_in2, var_tmp2d) ELSE CALL grille_m(iml_dyn, jml_dyn, lon_rad, lat_rad, . var_ana3d(:,:,il), iml-1, jml, lon_in, lat_in, var_tmp2d ) ENDIF ! CALL gr_int_dyn(var_tmp2d, var_tmp3d(:,:,il), iml-1, jml) ! ENDDO ! DO il=1,llm_dyn lind(il) = llm_dyn-il+1 ENDDO ! c c ... Pour l'interpolation verticale ,on interpole du haut de l'atmosphere c vers le sol ... c DO ij=1,jml DO ii=1,iml-1 ! ax(:) = lev_dyn(lind(:)) ay(:) = var_tmp3d(ii, ij, lind(:)) ! CALL SPLINE(ax, ay, llm_dyn, 1.e30, 1.e30, yder) ! DO il=1,lml bx = pls_in(ii, ij, il) CALL SPLINT(ax, ay, yder, llm_dyn, bx, by) var3d(ii, ij, il) = by ENDDO ! ENDDO var3d(iml, ij, :) = var3d(1, ij, :) ENDDO do il=1,lml call minmax(iml*jml,var3d(1,1,il),chmin,chmax) SELECTCASE(varname) CASE('U') WRITE(*,*) ' U min max l ',il,chmin,chmax CASE('V') WRITE(*,*) ' V min max l ',il,chmin,chmax CASE('TEMP') WRITE(*,*) ' TEMP min max l ',il,chmin,chmax CASE('R') WRITE(*,*) ' R min max l ',il,chmin,chmax END SELECT enddo DEALLOCATE(lon_rad) DEALLOCATE(lon_ini) DEALLOCATE(lat_rad) DEALLOCATE(lat_ini) DEALLOCATE(lev_dyn) DEALLOCATE(var_tmp2d) DEALLOCATE(var_tmp3d) DEALLOCATE(ax) DEALLOCATE(ay) DEALLOCATE(yder) DEALLOCATE(lind) ! RETURN ! END SUBROUTINE start_inter_3d ! #endif ! of #ifdef CPP_EARTH END MODULE startvar