Ignore:
Timestamp:
05/06/19 01:49:12 (5 years ago)
Author:
dubos
Message:

devel : towards Fortran driver for unstructured/LAM meshes

File:
1 edited

Legend:

Unmodified
Added
Removed
  • codes/icosagcm/devel/src/initial/etat0_collocated.f90

    r848 r856  
    11MODULE etat0_collocated_mod 
    22  USE icosa 
     3  USE grid_param 
    34  USE omp_para, ONLY : is_omp_level_master 
    45  USE caldyn_vars_mod, ONLY : hydrostatic 
     
    67  PRIVATE 
    78 
    8   LOGICAL :: autoinit_mass, autoinit_NH 
    99  CHARACTER(len=255),SAVE :: etat0_type 
    10 !$OMP THREADPRIVATE(autoinit_mass, autoinit_NH, etat0_type) 
     10!$OMP THREADPRIVATE(etat0_type) 
    1111 
    1212    PUBLIC :: etat0_type, etat0_collocated 
     
    3636    TYPE(t_field),POINTER :: f_q(:) 
    3737   
    38     TYPE(t_field),POINTER,SAVE :: f_temp(:) 
     38    TYPE(t_field),POINTER,SAVE :: f_temp(:) ! SAVE => all threads see the same f_temp 
    3939    REAL(rstd),POINTER :: ps(:) 
    4040    REAL(rstd),POINTER :: mass(:,:) 
     
    6464      q=f_q(ind) 
    6565 
    66       IF( TRIM(etat0_type)=='williamson91.6' ) THEN 
    67          CALL compute_etat0_collocated_hex(ps,mass, phis, theta_rhodz(:,:,1), u, geopot, W, q) 
    68       ELSE 
    69          CALL compute_etat0_collocated_hex(ps,mass, phis, temp, u, geopot, W, q) 
    70       ENDIF 
    71  
    72       IF( TRIM(etat0_type)/='williamson91.6' ) CALL compute_temperature2entropy(ps,temp,q,theta_rhodz, 1) 
    73      
     66      SELECT CASE(grid_type) 
     67      CASE(grid_ico) 
     68         CALL compute_etat0_collocated_hex(phis, ps, mass, theta_rhodz(:,:,1), u, geopot, W, q) 
     69      CASE(grid_unst) 
     70         CALL compute_etat0_collocated_unst(phis, ps, mass, theta_rhodz(:,:,1), u, geopot, W, q) 
     71      CASE DEFAULT 
     72         STOP 'Unexpected value of grid_type encountered in etat0_collocated.' 
     73      END SELECT 
     74 
    7475    ENDDO 
    7576     
     
    7879  END SUBROUTINE etat0_collocated 
    7980 
    80   SUBROUTINE compute_temperature2entropy(ps,temp,q,theta_rhodz,offset) 
    81     USE icosa 
    82     USE pression_mod 
    83     USE exner_mod 
    84     USE omp_para 
    85     REAL(rstd),INTENT(IN)  :: ps(iim*jjm) 
    86     REAL(rstd),INTENT(IN)  :: temp(iim*jjm,llm) 
    87     REAL(rstd),INTENT(IN)  :: q(iim*jjm,llm,nqtot) 
    88     REAL(rstd),INTENT(OUT) :: theta_rhodz(iim*jjm,llm) 
    89     INTEGER,INTENT(IN) :: offset 
    90  
    91     REAL(rstd) :: p(iim*jjm,llm+1) 
    92     REAL(rstd) :: cppd,Rd, mass, p_ij, q_ij,r_ij, chi,nu, entropy, theta 
    93     INTEGER :: i,j,ij,l 
    94  
    95     cppd=cpp 
    96     Rd=kappa*cppd 
    97  
    98     CALL compute_pression(ps,p,offset) 
    99     ! flush p 
    100     DO    l    = ll_begin, ll_end 
    101        DO j=jj_begin-offset,jj_end+offset 
    102           DO i=ii_begin-offset,ii_end+offset 
    103              ij=(j-1)*iim+i 
    104              mass = (p(ij,l)-p(ij,l+1))/g ! dry+moist mass 
    105              p_ij = .5*(p(ij,l)+p(ij,l+1))  ! pressure at full level 
    106              SELECT CASE(caldyn_thermo) 
    107              CASE(thermo_theta) 
    108                 theta = temp(ij,l)*(p_ij/preff)**(-kappa)  
    109                 theta_rhodz(ij,l) = mass * theta 
    110              CASE(thermo_entropy) 
    111                 nu = log(p_ij/preff) 
    112                 chi = log(temp(ij,l)/Treff) 
    113                 entropy = cppd*chi-Rd*nu 
    114                 theta_rhodz(ij,l) = mass * entropy 
    115 !             CASE(thermo_moist) 
    116 !                q_ij=q(ij,l,1) 
    117 !                r_ij=1.-q_ij 
    118 !                mass=mass*(1-q_ij) ! dry mass 
    119 !                nu = log(p_ij/preff) 
    120 !                chi = log(temp(ij,l)/Treff) 
    121 !                entropy = r_ij*(cppd*chi-Rd*nu) + q_ij*(cppv*chi-Rv*nu) 
    122 !                theta_rhodz(ij,l) = mass * entropy                 
    123                 CASE DEFAULT 
    124                    STOP 
    125              END SELECT 
    126           ENDDO 
    127        ENDDO 
    128     ENDDO 
    129   END SUBROUTINE compute_temperature2entropy 
    130  
    131   SUBROUTINE compute_etat0_collocated_hex(ps,mass,phis,temp_i,u, geopot,W, q) 
    132     USE wind_mod 
    133     USE disvert_mod 
     81  SUBROUTINE compute_etat0_collocated_hex(phis,ps,mass,theta_rhodz,u, geopot,W, q) 
    13482    REAL(rstd),INTENT(INOUT) :: ps(iim*jjm) 
    13583    REAL(rstd),INTENT(INOUT) :: mass(iim*jjm,llm) 
     84    REAL(rstd),INTENT(OUT) :: theta_rhodz(iim*jjm,llm) 
    13685    REAL(rstd),INTENT(OUT) :: phis(iim*jjm) 
    137     REAL(rstd),INTENT(OUT) :: temp_i(iim*jjm,llm) 
    13886    REAL(rstd),INTENT(OUT) :: u(3*iim*jjm,llm) 
    13987    REAL(rstd),INTENT(OUT) :: W(iim*jjm,llm+1) 
     
    14189    REAL(rstd),INTENT(OUT) :: q(iim*jjm,llm,nqtot) 
    14290 
    143     REAL(rstd) :: ulon_i(iim*jjm,llm) 
    144     REAL(rstd) :: ulat_i(iim*jjm,llm) 
    145  
    14691    REAL(rstd) :: ps_e(3*iim*jjm) 
     92    REAL(rstd) :: phis_e(3*iim*jjm) 
    14793    REAL(rstd) :: mass_e(3*iim*jjm,llm) 
    148     REAL(rstd) :: phis_e(3*iim*jjm) 
    149     REAL(rstd) :: temp_e(3*iim*jjm,llm) 
    15094    REAL(rstd) :: geopot_e(3*iim*jjm,llm+1) 
    151     REAL(rstd) :: ulon_e(3*iim*jjm,llm) 
    152     REAL(rstd) :: ulat_e(3*iim*jjm,llm) 
    15395    REAL(rstd) :: q_e(3*iim*jjm,llm,nqtot) 
    15496 
    155     INTEGER :: l,i,j,ij 
    156     REAL :: p_ik, v_ik, mass_ik 
    157  
    158     ! For NH geopotential and vertical momentum must be initialized. 
    159     ! Unless autoinit_NH is set to .FALSE. , they will be initialized 
    160     ! to hydrostatic geopotential and zero 
    161     autoinit_mass = .TRUE. 
    162     autoinit_NH = .NOT. hydrostatic 
    16397    w(:,:) = 0 
    164  
    165     CALL compute_etat0_collocated(iim*jjm  , lon_i, lat_i, phis,   ps,   mass,   temp_i, ulon_i, ulat_i, geopot,   q) 
    166     CALL compute_etat0_collocated(3*iim*jjm, lon_e, lat_e, phis_e, ps_e, mass_e, temp_e, ulon_e, ulat_e, geopot_e, q_e) 
    167  
    168     IF(autoinit_mass) CALL compute_rhodz(.TRUE., ps, mass) ! initialize mass distribution using ps 
    169     IF(autoinit_NH) THEN 
    170        geopot(:,1) = phis(:) ! surface geopotential 
    171        DO l = 1, llm 
    172           DO ij=1,iim*jjm 
    173              ! hybrid pressure coordinate 
    174              p_ik = ptop + mass_ak(l) + mass_bk(l)*ps(ij) 
    175              mass_ik = (mass_dak(l) + mass_dbk(l)*ps(ij))/g 
    176              ! v=R.T/p, R=kappa*cpp 
    177              v_ik = kappa*cpp*temp_i(ij,l)/p_ik 
    178              geopot(ij,l+1) = geopot(ij,l) + mass_ik*v_ik*g 
    179           END DO 
    180        END DO 
    181     END IF 
    182  
    183     CALL compute_wind_perp_from_lonlat_compound(ulon_e, ulat_e, u) 
     98    CALL compute_etat0_collocated(iim*jjm  , lon_i, lat_i, phis,   ps,   mass,   theta_rhodz, geopot,   q) 
     99    CALL compute_etat0_collocated(3*iim*jjm, lon_e, lat_e, phis_e, ps_e, mass_e, mass_e, geopot_e, q_e, ep_e, u) 
    184100 
    185101  END SUBROUTINE compute_etat0_collocated_hex 
    186102 
    187   SUBROUTINE compute_etat0_collocated(ngrid, lon, lat, phis, ps, mass, temp, ulon, ulat, geopot, q) 
     103  SUBROUTINE compute_etat0_collocated_unst(phis,ps,mass,theta_rhodz,u, geopot,W, q) 
     104    REAL(rstd),INTENT(INOUT) :: ps(primal_num) 
     105    REAL(rstd),INTENT(INOUT) :: mass(llm,primal_num) 
     106    REAL(rstd),INTENT(OUT) :: theta_rhodz(llm,primal_num) 
     107    REAL(rstd),INTENT(OUT) :: phis(primal_num) 
     108    REAL(rstd),INTENT(OUT) :: u(llm, edge_num) 
     109    REAL(rstd),INTENT(OUT) :: W(llm+1, primal_num) 
     110    REAL(rstd),INTENT(OUT) :: geopot(llm+1, primal_num) 
     111    REAL(rstd),INTENT(OUT) :: q(llm, primal_num, nqtot) 
     112    ! The 2D/3D arrays below have the shape expected by compute_etat0_collocated 
     113    REAL(rstd) :: ps_e(edge_num) 
     114    REAL(rstd) :: phis_e(edge_num) 
     115    REAL(rstd) :: u_e(edge_num, llm) 
     116    REAL(rstd) :: mass_i(primal_num, llm), theta_rhodz_i(primal_num, llm), mass_e(edge_num, llm) 
     117    REAL(rstd) :: geopot_i(edge_num, llm+1), geopot_e(edge_num, llm+1) 
     118    REAL(rstd) :: q_i(primal_num, llm, nqtot), q_e(edge_num, llm, nqtot) 
     119    INTEGER :: iq 
     120 
     121    w(:,:) = 0 
     122    CALL compute_etat0_collocated(primal_num  , lon_i, lat_i, phis,   ps,   mass_i,   theta_rhodz_i, geopot_i,   q_i) 
     123    CALL compute_etat0_collocated(edge_num, lon_e, lat_e, phis_e, ps_e, mass_e, mass_e, geopot_e, q_e, ep_e, u_e) 
     124    mass = TRANSPOSE(mass_i) 
     125    theta_rhodz = TRANSPOSE(theta_rhodz_i) 
     126    geopot = TRANSPOSE(geopot_i) 
     127    u = TRANSPOSE(u_e) 
     128    DO iq=1,nqtot 
     129       q(:,:,iq) = TRANSPOSE(q_i(:,:,iq)) 
     130    END DO 
     131  END SUBROUTINE compute_etat0_collocated_unst 
     132   
     133  SUBROUTINE compute_etat0_collocated(ngrid, lon, lat, phis, ps, mass, theta_rhodz, geopot, q, ep, uperp) 
    188134    USE etat0_isothermal_mod, ONLY : compute_isothermal => compute_etat0 
    189135    USE etat0_jablonowsky06_mod, ONLY : compute_jablonowsky06 => compute_etat0 
     
    199145    USE etat0_dcmip2016_cyclone_mod, ONLY : compute_dcmip2016_cyclone => compute_etat0 
    200146    USE etat0_dcmip2016_supercell_mod, ONLY : compute_dcmip2016_supercell => compute_etat0 
     147    USE disvert_mod, ONLY : ptop, ap, bp, mass_ak, mass_bk, mass_dak, mass_dbk 
    201148    INTEGER :: ngrid 
    202149    REAL(rstd),INTENT(IN)    :: lon(ngrid), lat(ngrid) 
    203150    REAL(rstd),INTENT(INOUT) :: ps(ngrid) 
    204151    REAL(rstd),INTENT(INOUT) :: mass(ngrid,llm) 
     152    REAL(rstd),INTENT(OUT)   :: theta_rhodz(ngrid,llm) 
    205153    REAL(rstd),INTENT(OUT)   :: phis(ngrid) 
    206     REAL(rstd),INTENT(OUT)   :: temp(ngrid,llm) 
    207     REAL(rstd),INTENT(OUT)   :: ulon(ngrid,llm) 
    208     REAL(rstd),INTENT(OUT)   :: ulat(ngrid,llm) 
    209154    REAL(rstd),INTENT(OUT)   :: geopot(ngrid,llm+1) 
    210155    REAL(rstd),INTENT(OUT)   :: q(ngrid,llm,nqtot) 
     156    REAL(rstd),INTENT(OUT), OPTIONAL   :: ep(ngrid,3), uperp(ngrid,llm) 
     157 
     158    REAL(rstd)   :: ulon(ngrid,llm) 
     159    REAL(rstd)   :: ulat(ngrid,llm) 
     160    REAL(rstd)   :: temp(ngrid,llm) 
     161 
     162    LOGICAL :: autoinit_mass, autoinit_NH 
     163    INTEGER :: ij,l 
     164    REAL(rstd) :: clat, slat, clon, slon, u3d(3), p_ik, mass_ik, v_ik 
     165    REAL(rstd) :: q_ik, r_ik, chi, entropy, theta, log_p_preff 
     166 
     167    ! For NH, geopotential and vertical momentum must be initialized. 
     168    ! Unless autoinit_NH is set to .FALSE. , they will be initialized 
     169    ! to hydrostatic geopotential and zero 
     170    autoinit_mass = .TRUE. 
     171    autoinit_NH = .NOT. hydrostatic 
    211172 
    212173    SELECT CASE (TRIM(etat0_type)) 
     
    232193!       autoinit_NH = .FALSE. ! compute_bubble initializes geopot 
    233194    CASE('williamson91.6') 
    234        CALL compute_w91_6(ngrid, lon, lat, phis, mass(:,1), temp(:,1), ulon(:,1), ulat(:,1)) 
     195       CALL compute_w91_6(ngrid, lon, lat, phis, mass(:,1), theta_rhodz(:,1), ulon(:,1), ulat(:,1)) 
    235196       autoinit_mass = .FALSE. ! do not overwrite mass 
    236197    CASE('dcmip2016_baroclinic_wave') 
     
    242203    END SELECT 
    243204 
     205    IF(PRESENT(uperp)) THEN 
     206       DO l = 1, llm 
     207          DO ij=1,ngrid 
     208             clat = COS(lat(ij)) 
     209             slat = SIN(lat(ij)) 
     210             clon = COS(lon(ij)) 
     211             slon = SIN(lon(ij)) 
     212             u3d(1) = -clon*slat*ulat(ij,l) - slon*ulon(ij,l) 
     213             u3d(2) = -slon*slat*ulat(ij,l) + clon*ulon(ij,l) 
     214             u3d(3) =       clat*ulat(ij,l)     
     215             uperp(ij,l) = SUM(u3d*ep(ij,:)) 
     216          END DO 
     217       END DO 
     218    END IF 
     219 
     220    IF(autoinit_mass) THEN 
     221       DO l = 1, llm 
     222          DO ij=1,ngrid 
     223             mass_ik = (mass_dak(l) + mass_dbk(l)*ps(ij))/g 
     224             p_ik = ptop + mass_ak(l) + mass_bk(l)*ps(ij) 
     225             mass(ij,l) = mass_ik 
     226             SELECT CASE(caldyn_thermo) 
     227             CASE(thermo_theta) 
     228                theta = temp(ij,l)*(p_ik/preff)**(-kappa) 
     229                theta_rhodz(ij,l) = mass_ik * theta 
     230             CASE(thermo_entropy) 
     231                log_p_preff = log(p_ik/preff) 
     232                chi = log(temp(ij,l)/Treff) 
     233                entropy = cpp*chi-Rd*log_p_preff 
     234                theta_rhodz(ij,l) = mass_ik * entropy 
     235             CASE(thermo_moist) 
     236                q_ik=q(ij,l,1) 
     237                r_ik=1.-q_ik 
     238                mass_ik = mass_ik*(1.-q_ik) ! dry mass 
     239                log_p_preff = log(p_ik/preff) 
     240                chi = log(temp(ij,l)/Treff) 
     241                entropy = r_ik*(cpp*chi-Rd*nu) + q_ik*(cppv*chi-Rv*log_p_preff) 
     242                theta_rhodz(ij,l) = mass_ik * entropy 
     243             CASE DEFAULT 
     244                STOP 
     245             END SELECT 
     246          END DO 
     247       END DO 
     248    END IF 
     249 
     250    IF(autoinit_NH) THEN 
     251       geopot(:,1) = phis(:) ! surface geopotential 
     252       DO l = 1, llm 
     253          DO ij=1,ngrid 
     254             ! hybrid pressure coordinate 
     255             p_ik = ptop + mass_ak(l) + mass_bk(l)*ps(ij) 
     256             mass_ik = (mass_dak(l) + mass_dbk(l)*ps(ij))/g 
     257             ! v=R.T/p, R=kappa*cpp 
     258             v_ik = kappa*cpp*temp(ij,l)/p_ik 
     259             geopot(ij,l+1) = geopot(ij,l) + mass_ik*v_ik*g 
     260          END DO 
     261       END DO 
     262    END IF 
     263 
    244264  END SUBROUTINE compute_etat0_collocated 
    245265 
Note: See TracChangeset for help on using the changeset viewer.