! $Id$ MODULE guide_mod !======================================================================= ! Auteur: F.Hourdin ! F. Codron 01/09 !======================================================================= USE getparam, ONLY: ini_getparam, fin_getparam, getpar USE lmdz_write_field USE netcdf, ONLY: nf90_nowrite, nf90_open, nf90_inq_varid, nf90_close, & nf90_inq_dimid, nf90_inquire_dimension, nf90_float, nf90_def_var, & nf90_create, nf90_def_dim, nf90_open, nf90_unlimited, nf90_write, nf90_enddef, nf90_redef, & nf90_close, nf90_inq_varid, nf90_get_var, nf90_noerr, nf90_clobber, & nf90_64bit_offset, nf90_inq_dimid, nf90_inquire_dimension, nf90_put_var USE lmdz_pres2lev, ONLY: pres2lev IMPLICIT NONE ! --------------------------------------------- ! Declarations des cles logiques et parametres ! --------------------------------------------- INTEGER, PRIVATE, SAVE :: iguide_read, iguide_int, iguide_sav INTEGER, PRIVATE, SAVE :: nlevnc, guide_plevs LOGICAL, PRIVATE, SAVE :: guide_u, guide_v, guide_T, guide_Q, guide_P LOGICAL, PRIVATE, SAVE :: guide_hr, guide_teta LOGICAL, PRIVATE, SAVE :: guide_BL, guide_reg, guide_add, gamma4, guide_zon LOGICAL, PRIVATE, SAVE :: invert_p, invert_y, ini_anal LOGICAL, PRIVATE, SAVE :: guide_2D, guide_sav, guide_modele !FC LOGICAL, PRIVATE, SAVE :: convert_Pa REAL, PRIVATE, SAVE :: tau_min_u, tau_max_u REAL, PRIVATE, SAVE :: tau_min_v, tau_max_v REAL, PRIVATE, SAVE :: tau_min_T, tau_max_T REAL, PRIVATE, SAVE :: tau_min_Q, tau_max_Q REAL, PRIVATE, SAVE :: tau_min_P, tau_max_P REAL, PRIVATE, SAVE :: lat_min_g, lat_max_g REAL, PRIVATE, SAVE :: lon_min_g, lon_max_g REAL, PRIVATE, SAVE :: tau_lon, tau_lat REAL, PRIVATE, SAVE :: plim_guide_BL REAL, ALLOCATABLE, DIMENSION(:), PRIVATE, SAVE :: alpha_u, alpha_v REAL, ALLOCATABLE, DIMENSION(:, :), PRIVATE, SAVE :: alpha_T, alpha_Q REAL, ALLOCATABLE, DIMENSION(:), PRIVATE, SAVE :: alpha_P, alpha_pcor ! --------------------------------------------- ! Variables de guidage ! --------------------------------------------- ! Variables des fichiers de guidage REAL, ALLOCATABLE, DIMENSION(:, :, :), PRIVATE, SAVE :: unat1, unat2 REAL, ALLOCATABLE, DIMENSION(:, :, :), PRIVATE, SAVE :: vnat1, vnat2 REAL, ALLOCATABLE, DIMENSION(:, :, :), PRIVATE, SAVE :: tnat1, tnat2 REAL, ALLOCATABLE, DIMENSION(:, :, :), PRIVATE, SAVE :: qnat1, qnat2 REAL, ALLOCATABLE, DIMENSION(:, :, :), PRIVATE, SAVE :: pnat1, pnat2 REAL, ALLOCATABLE, DIMENSION(:, :), PRIVATE, SAVE :: psnat1, psnat2 REAL, ALLOCATABLE, DIMENSION(:), PRIVATE, SAVE :: apnc, bpnc ! Variables aux dimensions du modele REAL, ALLOCATABLE, DIMENSION(:, :), PRIVATE, SAVE :: ugui1, ugui2 REAL, ALLOCATABLE, DIMENSION(:, :), PRIVATE, SAVE :: vgui1, vgui2 REAL, ALLOCATABLE, DIMENSION(:, :), PRIVATE, SAVE :: tgui1, tgui2 REAL, ALLOCATABLE, DIMENSION(:, :), PRIVATE, SAVE :: qgui1, qgui2 REAL, ALLOCATABLE, DIMENSION(:), PRIVATE, SAVE :: psgui1, psgui2 CONTAINS !======================================================================= SUBROUTINE guide_init USE netcdf, ONLY: nf90_noerr USE control_mod, ONLY: day_step USE serre_mod, ONLY: grossismx IMPLICIT NONE INCLUDE "dimensions.h" INCLUDE "paramet.h" INTEGER :: error, ncidpl, rid, rcod CHARACTER (len = 80) :: abort_message CHARACTER (len = 20) :: modname = 'guide_init' CHARACTER (len = 20) :: namedim ! --------------------------------------------- ! Lecture des parametres: ! --------------------------------------------- CALL ini_getparam("nudging_parameters_out.txt") ! Variables guidees CALL getpar('guide_u', .TRUE., guide_u, 'guidage de u') CALL getpar('guide_v', .TRUE., guide_v, 'guidage de v') CALL getpar('guide_T', .TRUE., guide_T, 'guidage de T') CALL getpar('guide_P', .TRUE., guide_P, 'guidage de P') CALL getpar('guide_Q', .TRUE., guide_Q, 'guidage de Q') CALL getpar('guide_hr', .TRUE., guide_hr, 'guidage de Q par H.R') CALL getpar('guide_teta', .FALSE., guide_teta, 'guidage de T par Teta') CALL getpar('guide_add', .FALSE., guide_add, 'forçage constant?') CALL getpar('guide_zon', .FALSE., guide_zon, 'guidage moy zonale') IF (guide_zon .AND. abs(grossismx - 1.) > 0.01) & CALL abort_gcm("guide_init", & "zonal nudging requires grid regular in longitude", 1) ! Constantes de rappel. Unite : fraction de jour CALL getpar('tau_min_u', 0.02, tau_min_u, 'Cste de rappel min, u') CALL getpar('tau_max_u', 10., tau_max_u, 'Cste de rappel max, u') CALL getpar('tau_min_v', 0.02, tau_min_v, 'Cste de rappel min, v') CALL getpar('tau_max_v', 10., tau_max_v, 'Cste de rappel max, v') CALL getpar('tau_min_T', 0.02, tau_min_T, 'Cste de rappel min, T') CALL getpar('tau_max_T', 10., tau_max_T, 'Cste de rappel max, T') CALL getpar('tau_min_Q', 0.02, tau_min_Q, 'Cste de rappel min, Q') CALL getpar('tau_max_Q', 10., tau_max_Q, 'Cste de rappel max, Q') CALL getpar('tau_min_P', 0.02, tau_min_P, 'Cste de rappel min, P') CALL getpar('tau_max_P', 10., tau_max_P, 'Cste de rappel max, P') CALL getpar('gamma4', .FALSE., gamma4, 'Zone sans rappel elargie') CALL getpar('guide_BL', .TRUE., guide_BL, 'guidage dans C.Lim') CALL getpar('plim_guide_BL', 85000., plim_guide_BL, 'BL top presnivs value') ! Sauvegarde du forçage CALL getpar('guide_sav', .FALSE., guide_sav, 'sauvegarde guidage') CALL getpar('iguide_sav', 4, iguide_sav, 'freq. sauvegarde guidage') ! frequences f>0: fx/jour; f<0: tous les f jours; f=0: 1 seule fois. IF (iguide_sav>0) THEN iguide_sav = day_step / iguide_sav ELSE if (iguide_sav == 0) THEN iguide_sav = huge(0) ELSE iguide_sav = day_step * iguide_sav ENDIF ! Guidage regional seulement (sinon constant ou suivant le zoom) CALL getpar('guide_reg', .FALSE., guide_reg, 'guidage regional') CALL getpar('lat_min_g', -90., lat_min_g, 'Latitude mini guidage ') CALL getpar('lat_max_g', 90., lat_max_g, 'Latitude maxi guidage ') CALL getpar('lon_min_g', -180., lon_min_g, 'longitude mini guidage ') CALL getpar('lon_max_g', 180., lon_max_g, 'longitude maxi guidage ') CALL getpar('tau_lat', 5., tau_lat, 'raideur lat guide regional ') CALL getpar('tau_lon', 5., tau_lon, 'raideur lon guide regional ') ! Parametres pour lecture des fichiers CALL getpar('iguide_read', 4, iguide_read, 'freq. lecture guidage') CALL getpar('iguide_int', 4, iguide_int, 'freq. interpolation vert') IF (iguide_int==0) THEN iguide_int = 1 ELSEIF (iguide_int>0) THEN iguide_int = day_step / iguide_int ELSE iguide_int = day_step * iguide_int ENDIF CALL getpar('guide_plevs', 0, guide_plevs, 'niveaux pression fichiers guidage') ! Pour compatibilite avec ancienne version avec guide_modele CALL getpar('guide_modele', .FALSE., guide_modele, 'niveaux pression ap+bp*psol') IF (guide_modele) THEN guide_plevs = 1 ENDIF !FC CALL getpar('convert_Pa', .TRUE., convert_Pa, 'Convert Pressure levels in Pa') ! Fin raccord CALL getpar('ini_anal', .FALSE., ini_anal, 'Etat initial = analyse') CALL getpar('guide_invertp', .TRUE., invert_p, 'niveaux p inverses') CALL getpar('guide_inverty', .TRUE., invert_y, 'inversion N-S') CALL getpar('guide_2D', .FALSE., guide_2D, 'fichier guidage lat-P') CALL fin_getparam ! --------------------------------------------- ! Determination du nombre de niveaux verticaux ! des fichiers guidage ! --------------------------------------------- ncidpl = -99 IF (guide_plevs==1) THEN IF (ncidpl==-99) THEN rcod = nf90_open('apbp.nc', nf90_nowrite, ncidpl) IF (rcod/=nf90_noerr) THEN abort_message = ' Nudging error -> no file apbp.nc' CALL abort_gcm(modname, abort_message, 1) endif endif elseif (guide_plevs==2) THEN IF (ncidpl==-99) THEN rcod = nf90_open('P.nc', nf90_nowrite, ncidpl) IF (rcod/=nf90_noerr) THEN abort_message = ' Nudging error -> no file P.nc' CALL abort_gcm(modname, abort_message, 1) endif endif elseif (guide_u) THEN IF (ncidpl==-99) THEN rcod = nf90_open('u.nc', nf90_nowrite, ncidpl) IF (rcod/=nf90_noerr) THEN CALL abort_gcm(modname, & ' Nudging error -> no file u.nc', 1) endif endif elseif (guide_v) THEN IF (ncidpl==-99) THEN rcod = nf90_open('v.nc', nf90_nowrite, ncidpl) IF (rcod/=nf90_noerr) THEN CALL abort_gcm(modname, & ' Nudging error -> no file v.nc', 1) endif endif elseif (guide_T) THEN IF (ncidpl==-99) THEN rcod = nf90_open('T.nc', nf90_nowrite, ncidpl) IF (rcod/=nf90_noerr) THEN CALL abort_gcm(modname, & ' Nudging error -> no file T.nc', 1) endif endif elseif (guide_Q) THEN IF (ncidpl==-99) THEN rcod = nf90_open('hur.nc', nf90_nowrite, ncidpl) IF (rcod/=nf90_noerr) THEN CALL abort_gcm(modname, & ' Nudging error -> no file hur.nc', 1) endif endif endif error = nf90_inq_dimid(ncidpl, 'LEVEL', rid) IF (error/=nf90_noerr) error = nf90_inq_dimid(ncidpl, 'PRESSURE', rid) IF (error/=nf90_noerr) THEN CALL abort_gcm(modname, 'Nudging: error reading pressure levels', 1) ENDIF error = nf90_inquire_dimension(ncidpl, rid, len = nlevnc) WRITE(*, *)trim(modname) // ' : number of vertical levels nlevnc', nlevnc rcod = nf90_close(ncidpl) ! --------------------------------------------- ! Allocation des variables ! --------------------------------------------- abort_message = 'nudging allocation error' ALLOCATE(apnc(nlevnc), stat = error) IF (error /= 0) CALL abort_gcm(modname, abort_message, 1) ALLOCATE(bpnc(nlevnc), stat = error) IF (error /= 0) CALL abort_gcm(modname, abort_message, 1) apnc = 0.;bpnc = 0. ALLOCATE(alpha_pcor(llm), stat = error) IF (error /= 0) CALL abort_gcm(modname, abort_message, 1) ALLOCATE(alpha_u(ip1jmp1), stat = error) IF (error /= 0) CALL abort_gcm(modname, abort_message, 1) ALLOCATE(alpha_v(ip1jm), stat = error) IF (error /= 0) CALL abort_gcm(modname, abort_message, 1) ALLOCATE(alpha_T(iip1, jjp1), stat = error) IF (error /= 0) CALL abort_gcm(modname, abort_message, 1) ALLOCATE(alpha_Q(iip1, jjp1), stat = error) IF (error /= 0) CALL abort_gcm(modname, abort_message, 1) ALLOCATE(alpha_P(ip1jmp1), stat = error) IF (error /= 0) CALL abort_gcm(modname, abort_message, 1) alpha_u = 0.;alpha_v = 0;alpha_T = 0;alpha_Q = 0;alpha_P = 0 IF (guide_u) THEN ALLOCATE(unat1(iip1, jjp1, nlevnc), stat = error) IF (error /= 0) CALL abort_gcm(modname, abort_message, 1) ALLOCATE(ugui1(ip1jmp1, llm), stat = error) IF (error /= 0) CALL abort_gcm(modname, abort_message, 1) ALLOCATE(unat2(iip1, jjp1, nlevnc), stat = error) IF (error /= 0) CALL abort_gcm(modname, abort_message, 1) ALLOCATE(ugui2(ip1jmp1, llm), stat = error) IF (error /= 0) CALL abort_gcm(modname, abort_message, 1) unat1 = 0.;unat2 = 0.;ugui1 = 0.;ugui2 = 0. ENDIF IF (guide_T) THEN ALLOCATE(tnat1(iip1, jjp1, nlevnc), stat = error) IF (error /= 0) CALL abort_gcm(modname, abort_message, 1) ALLOCATE(tgui1(ip1jmp1, llm), stat = error) IF (error /= 0) CALL abort_gcm(modname, abort_message, 1) ALLOCATE(tnat2(iip1, jjp1, nlevnc), stat = error) IF (error /= 0) CALL abort_gcm(modname, abort_message, 1) ALLOCATE(tgui2(ip1jmp1, llm), stat = error) IF (error /= 0) CALL abort_gcm(modname, abort_message, 1) tnat1 = 0.;tnat2 = 0.;tgui1 = 0.;tgui2 = 0. ENDIF IF (guide_Q) THEN ALLOCATE(qnat1(iip1, jjp1, nlevnc), stat = error) IF (error /= 0) CALL abort_gcm(modname, abort_message, 1) ALLOCATE(qgui1(ip1jmp1, llm), stat = error) IF (error /= 0) CALL abort_gcm(modname, abort_message, 1) ALLOCATE(qnat2(iip1, jjp1, nlevnc), stat = error) IF (error /= 0) CALL abort_gcm(modname, abort_message, 1) ALLOCATE(qgui2(ip1jmp1, llm), stat = error) IF (error /= 0) CALL abort_gcm(modname, abort_message, 1) qnat1 = 0.;qnat2 = 0.;qgui1 = 0.;qgui2 = 0. ENDIF IF (guide_v) THEN ALLOCATE(vnat1(iip1, jjm, nlevnc), stat = error) IF (error /= 0) CALL abort_gcm(modname, abort_message, 1) ALLOCATE(vgui1(ip1jm, llm), stat = error) IF (error /= 0) CALL abort_gcm(modname, abort_message, 1) ALLOCATE(vnat2(iip1, jjm, nlevnc), stat = error) IF (error /= 0) CALL abort_gcm(modname, abort_message, 1) ALLOCATE(vgui2(ip1jm, llm), stat = error) IF (error /= 0) CALL abort_gcm(modname, abort_message, 1) vnat1 = 0.;vnat2 = 0.;vgui1 = 0.;vgui2 = 0. ENDIF IF (guide_plevs==2) THEN ALLOCATE(pnat1(iip1, jjp1, nlevnc), stat = error) IF (error /= 0) CALL abort_gcm(modname, abort_message, 1) ALLOCATE(pnat2(iip1, jjp1, nlevnc), stat = error) IF (error /= 0) CALL abort_gcm(modname, abort_message, 1) pnat1 = 0.;pnat2 = 0.; ENDIF IF (guide_P.OR.guide_plevs==1) THEN ALLOCATE(psnat1(iip1, jjp1), stat = error) IF (error /= 0) CALL abort_gcm(modname, abort_message, 1) ALLOCATE(psnat2(iip1, jjp1), stat = error) IF (error /= 0) CALL abort_gcm(modname, abort_message, 1) psnat1 = 0.;psnat2 = 0.; ENDIF IF (guide_P) THEN ALLOCATE(psgui2(ip1jmp1), stat = error) IF (error /= 0) CALL abort_gcm(modname, abort_message, 1) ALLOCATE(psgui1(ip1jmp1), stat = error) IF (error /= 0) CALL abort_gcm(modname, abort_message, 1) psgui1 = 0.;psgui2 = 0. ENDIF ! --------------------------------------------- ! Lecture du premier etat de guidage. ! --------------------------------------------- IF (guide_2D) THEN CALL guide_read2D(1) ELSE CALL guide_read(1) ENDIF IF (guide_v) vnat1 = vnat2 IF (guide_u) unat1 = unat2 IF (guide_T) tnat1 = tnat2 IF (guide_Q) qnat1 = qnat2 IF (guide_plevs==2) pnat1 = pnat2 IF (guide_P.OR.guide_plevs==1) psnat1 = psnat2 END SUBROUTINE guide_init !======================================================================= SUBROUTINE guide_main(itau, ucov, vcov, teta, q, masse, ps) USE exner_hyb_m, ONLY: exner_hyb USE exner_milieu_m, ONLY: exner_milieu USE control_mod, ONLY: day_step, iperiod USE comconst_mod, ONLY: cpp, dtvr, daysec, kappa USE comvert_mod, ONLY: ap, bp, preff, presnivs, pressure_exner USE lmdz_iniprint, ONLY: lunout, prt_level IMPLICIT NONE INCLUDE "dimensions.h" INCLUDE "paramet.h" ! Variables entree INTEGER, INTENT(IN) :: itau !pas de temps REAL, DIMENSION (ip1jmp1, llm), INTENT(INOUT) :: ucov, teta, q, masse REAL, DIMENSION (ip1jm, llm), INTENT(INOUT) :: vcov REAL, DIMENSION (ip1jmp1), INTENT(INOUT) :: ps ! Variables locales LOGICAL, SAVE :: first = .TRUE. LOGICAL :: f_out ! sortie guidage REAL, DIMENSION (ip1jmp1, llm) :: f_add ! var aux: champ de guidage REAL :: pk(ip1jmp1, llm) ! Exner at mid-layers REAL :: pks(ip1jmp1) ! Exner at the surface REAL :: unskap ! 1./kappa REAL, DIMENSION (ip1jmp1, llmp1) :: p ! Pressure at inter-layers ! Compteurs temps: INTEGER, SAVE :: step_rea, count_no_rea, itau_test ! lecture guidage REAL :: ditau, dday_step REAL :: tau, reste ! position entre 2 etats de guidage REAL, SAVE :: factt ! pas de temps en fraction de jour INTEGER :: l CHARACTER(LEN = 20) :: modname = "guide_main" CHARACTER (len = 80) :: abort_message !----------------------------------------------------------------------- ! Initialisations au premier passage !----------------------------------------------------------------------- IF (first) THEN first = .FALSE. CALL guide_init itau_test = 1001 step_rea = 1 count_no_rea = 0 ! Calcul des constantes de rappel factt = dtvr * iperiod / daysec CALL tau2alpha(3, iip1, jjm, factt, tau_min_v, tau_max_v, alpha_v) CALL tau2alpha(2, iip1, jjp1, factt, tau_min_u, tau_max_u, alpha_u) CALL tau2alpha(1, iip1, jjp1, factt, tau_min_T, tau_max_T, alpha_T) CALL tau2alpha(1, iip1, jjp1, factt, tau_min_P, tau_max_P, alpha_P) CALL tau2alpha(1, iip1, jjp1, factt, tau_min_Q, tau_max_Q, alpha_Q) ! correction de rappel dans couche limite IF (guide_BL) THEN alpha_pcor(:) = 1. else do l = 1, llm alpha_pcor(l) = (1. + tanh(((plim_guide_BL - presnivs(l)) / preff) / 0.05)) / 2. enddo endif ! ini_anal: etat initial egal au guidage IF (ini_anal) THEN CALL guide_interp(ps, teta) IF (guide_u) ucov = ugui2 IF (guide_v) vcov = ugui2 IF (guide_T) teta = tgui2 IF (guide_Q) q = qgui2 IF (guide_P) THEN ps = psgui2 CALL pression(ip1jmp1, ap, bp, ps, p) CALL massdair(p, masse) ENDIF ENDIF ! Verification structure guidage ! IF (guide_u) THEN ! CALL writefield('unat',unat1) ! CALL writefield('ucov',RESHAPE(ucov,(/iip1,jjp1,llm/))) ! ENDIF ! IF (guide_T) THEN ! CALL writefield('tnat',tnat1) ! CALL writefield('teta',RESHAPE(teta,(/iip1,jjp1,llm/))) ! ENDIF ENDIF !first !----------------------------------------------------------------------- ! Lecture des fichiers de guidage ? !----------------------------------------------------------------------- IF (iguide_read/=0) THEN ditau = real(itau) dday_step = real(day_step) IF (iguide_read<0) THEN tau = ditau / dday_step / REAL(iguide_read) ELSE tau = REAL(iguide_read) * ditau / dday_step ENDIF reste = tau - AINT(tau) IF (reste==0.) THEN IF (itau_test==itau) THEN WRITE(lunout, *)trim(modname) // ' second pass in advreel at itau=', & itau abort_message = 'stopped' CALL abort_gcm(modname, abort_message, 1) ELSE IF (guide_v) vnat1 = vnat2 IF (guide_u) unat1 = unat2 IF (guide_T) tnat1 = tnat2 IF (guide_Q) qnat1 = qnat2 IF (guide_plevs==2) pnat1 = pnat2 IF (guide_P.OR.guide_plevs==1) psnat1 = psnat2 step_rea = step_rea + 1 itau_test = itau WRITE(*, *)trim(modname) // ' Reading nudging files, step ', & step_rea, 'after ', count_no_rea, ' skips' IF (guide_2D) THEN CALL guide_read2D(step_rea) ELSE CALL guide_read(step_rea) ENDIF count_no_rea = 0 ENDIF ELSE count_no_rea = count_no_rea + 1 ENDIF ENDIF !iguide_read=0 !----------------------------------------------------------------------- ! Interpolation et conversion des champs de guidage !----------------------------------------------------------------------- IF (MOD(itau, iguide_int)==0) THEN CALL guide_interp(ps, teta) ENDIF ! Repartition entre 2 etats de guidage IF (iguide_read/=0) THEN tau = reste ELSE tau = 1. ENDIF !----------------------------------------------------------------------- ! Ajout des champs de guidage !----------------------------------------------------------------------- ! Sauvegarde du guidage? f_out = ((MOD(itau, iguide_sav)==0).AND.guide_sav) IF (f_out) THEN ! compute pressures at layer interfaces CALL pression(ip1jmp1, ap, bp, ps, p) IF (pressure_exner) THEN CALL exner_hyb(ip1jmp1, ps, p, pks, pk) else CALL exner_milieu(ip1jmp1, ps, p, pks, pk) endif unskap = 1. / kappa ! Now compute pressures at mid-layer do l = 1, llm p(:, l) = preff * (pk(:, l) / cpp)**unskap enddo CALL guide_out("SP", jjp1, llm, p(:, 1:llm)) ENDIF IF (guide_u) THEN IF (guide_add) THEN f_add = (1. - tau) * ugui1 + tau * ugui2 else f_add = (1. - tau) * ugui1 + tau * ugui2 - ucov endif IF (guide_zon) CALL guide_zonave(1, jjp1, llm, f_add) CALL guide_addfield(ip1jmp1, llm, f_add, alpha_u) IF (f_out) CALL guide_out("ua", jjp1, llm, (1. - tau) * ugui1 + tau * ugui2) IF (f_out) CALL guide_out("u", jjp1, llm, ucov) IF (f_out) CALL guide_out("ucov", jjp1, llm, f_add / factt) ucov = ucov + f_add endif IF (guide_T) THEN IF (guide_add) THEN f_add = (1. - tau) * tgui1 + tau * tgui2 else f_add = (1. - tau) * tgui1 + tau * tgui2 - teta endif IF (guide_zon) CALL guide_zonave(2, jjp1, llm, f_add) CALL guide_addfield(ip1jmp1, llm, f_add, alpha_T) IF (f_out) CALL guide_out("teta", jjp1, llm, f_add / factt) teta = teta + f_add endif IF (guide_P) THEN IF (guide_add) THEN f_add(1:ip1jmp1, 1) = (1. - tau) * psgui1 + tau * psgui2 else f_add(1:ip1jmp1, 1) = (1. - tau) * psgui1 + tau * psgui2 - ps endif IF (guide_zon) CALL guide_zonave(2, jjp1, 1, f_add(1:ip1jmp1, 1)) CALL guide_addfield(ip1jmp1, 1, f_add(1:ip1jmp1, 1), alpha_P) ! IF (f_out) CALL guide_out("ps",jjp1,1,f_add(1:ip1jmp1,1)/factt) ps = ps + f_add(1:ip1jmp1, 1) CALL pression(ip1jmp1, ap, bp, ps, p) CALL massdair(p, masse) endif IF (guide_Q) THEN IF (guide_add) THEN f_add = (1. - tau) * qgui1 + tau * qgui2 else f_add = (1. - tau) * qgui1 + tau * qgui2 - q endif IF (guide_zon) CALL guide_zonave(2, jjp1, llm, f_add) CALL guide_addfield(ip1jmp1, llm, f_add, alpha_Q) IF (f_out) CALL guide_out("q", jjp1, llm, f_add / factt) q = q + f_add endif IF (guide_v) THEN IF (guide_add) THEN f_add(1:ip1jm, :) = (1. - tau) * vgui1 + tau * vgui2 else f_add(1:ip1jm, :) = (1. - tau) * vgui1 + tau * vgui2 - vcov endif IF (guide_zon) CALL guide_zonave(2, jjm, llm, f_add(1:ip1jm, :)) CALL guide_addfield(ip1jm, llm, f_add(1:ip1jm, :), alpha_v) IF (f_out) CALL guide_out("v", jjm, llm, vcov) IF (f_out) CALL guide_out("va", jjm, llm, (1. - tau) * vgui1 + tau * vgui2) IF (f_out) CALL guide_out("vcov", jjm, llm, f_add(1:ip1jm, :) / factt) vcov = vcov + f_add(1:ip1jm, :) endif END SUBROUTINE guide_main !======================================================================= SUBROUTINE guide_addfield(hsize, vsize, field, alpha) ! field1=a*field1+alpha*field2 IMPLICIT NONE ! input variables INTEGER, INTENT(IN) :: hsize INTEGER, INTENT(IN) :: vsize REAL, DIMENSION(hsize), INTENT(IN) :: alpha REAL, DIMENSION(hsize, vsize), INTENT(INOUT) :: field ! Local variables INTEGER :: l do l = 1, vsize field(:, l) = alpha * field(:, l) * alpha_pcor(l) enddo END SUBROUTINE guide_addfield !======================================================================= SUBROUTINE guide_zonave(typ, hsize, vsize, field) USE comconst_mod, ONLY: pi USE lmdz_comgeom IMPLICIT NONE INCLUDE "dimensions.h" INCLUDE "paramet.h" ! input/output variables INTEGER, INTENT(IN) :: typ INTEGER, INTENT(IN) :: vsize INTEGER, INTENT(IN) :: hsize REAL, DIMENSION(hsize * iip1, vsize), INTENT(INOUT) :: field ! Local variables LOGICAL, SAVE :: first = .TRUE. INTEGER, DIMENSION (2), SAVE :: imin, imax ! averaging domain INTEGER :: i, j, l, ij REAL, DIMENSION (iip1) :: lond ! longitude in Deg. REAL, DIMENSION (hsize, vsize) :: fieldm ! zon-averaged field IF (first) THEN first = .FALSE. !Compute domain for averaging lond = rlonu * 180. / pi imin(1) = 1;imax(1) = iip1; imin(2) = 1;imax(2) = iip1; IF (guide_reg) THEN DO i = 1, iim IF (lond(i)1.e10) THEN zz = 0.5 * (x(i - 1, l) + x(i + 1, l)) PRINT*, 'correction ', i, l, x(i, l), zz x(i, l) = zz endif enddo enddo END SUBROUTINE correctbid !=========================================================================== END MODULE guide_mod