source: codes/icosagcm/devel/src/physics/physics.f90 @ 726

Last change on this file since 726 was 726, checked in by dubos, 6 years ago

devel : backported from trunk commits r707-r711,r713

File size: 12.7 KB
RevLine 
[81]1MODULE physics_mod
[714]2  USE icosa
[196]3  USE field_mod
[714]4  USE physics_interface_mod
5  USE omp_para
6  IMPLICIT NONE
[196]7  PRIVATE
8
[402]9  INTEGER, PARAMETER :: phys_none=0, phys_HS94=1, phys_DCMIP=2, phys_lmdz_generic=3, phys_LB2012=4, phys_external=5,&
10                        phys_DCMIP2016=6
[196]11
[213]12  INTEGER :: phys_type
[481]13  TYPE(t_field),POINTER,SAVE :: f_extra_physics_2D(:), f_extra_physics_3D(:)
14  TYPE(t_field),POINTER,SAVE :: f_dulon(:), f_dulat(:)
15  TYPE(t_field),POINTER,SAVE :: f_ulon(:), f_ulat(:)
16  TYPE(t_field),POINTER,SAVE :: f_p(:), f_pk(:)
17  TYPE(t_field),POINTER,SAVE :: f_temp(:)
[714]18  TYPE(t_field),POINTER,SAVE :: f_du_phys(:)
[196]19
[481]20  CHARACTER(LEN=255),SAVE :: physics_type
[186]21!$OMP THREADPRIVATE(physics_type)
[81]22
[714]23  PUBLIC :: physics, init_physics, zero_du_phys
[213]24
[81]25CONTAINS
26
[98]27  SUBROUTINE init_physics
[178]28    USE mpipara
29    USE etat0_mod
[215]30    USE physics_dcmip_mod, ONLY : init_physics_dcmip=>init_physics
[381]31    USE physics_dcmip2016_mod, ONLY : init_physics_dcmip2016=>init_physics
[325]32    USE etat0_venus_mod, ONLY : init_phys_venus=>init_physics
[327]33    USE physics_lmdz_generic_mod, ONLY : init_physics_lmdz_generic=>init_physics
[347]34    USE physics_external_mod, ONLY : init_physics_external=>init_physics
[170]35
[217]36    physics_inout%dt_phys = dt*itau_physics
37    physics_type='none'
[81]38    CALL getin("physics",physics_type)
39    SELECT CASE(TRIM(physics_type))
[217]40    CASE ('none')
[726]41
42!$OMP PARALLEL
[217]43       IF(is_mpi_root) PRINT*,"NO PHYSICAL PACKAGE USED"
44       phys_type = phys_none
[726]45!$OMP END PARALLEL
46
[217]47    CASE ('held_suarez')
[726]48
49!$OMP PARALLEL
[217]50       phys_type = phys_HS94
[726]51!$OMP END PARALLEL
52
[325]53    CASE ('Lebonnois2012')
[726]54
55!$OMP PARALLEL
[325]56       phys_type = phys_LB2012
57       CALL init_phys_venus
[726]58!$OMP END PARALLEL
[327]59
60    CASE ('phys_lmdz_generic')
[726]61
62!$OMP PARALLEL
[327]63       CALL init_physics_lmdz_generic
64       phys_type=phys_lmdz_generic
[726]65!$OMP END PARALLEL
66
[347]67    CASE ('phys_external')
[726]68
[347]69       CALL init_physics_external
[726]70!$OMP PARALLEL
[347]71       phys_type=phys_external
[726]72!$OMP END PARALLEL
73
[170]74    CASE ('dcmip')
[726]75
76!$OMP PARALLEL
[217]77       CALL allocate_field(f_dulon,field_t,type_real,llm, name='dulon')
78       CALL allocate_field(f_dulat,field_t,type_real,llm, name='dulat')
[295]79       CALL allocate_field(f_temp,field_t,type_real,llm, name='temp')
[481]80       CALL allocate_field(f_ulon,field_t,type_real,llm, name='ulon')
81       CALL allocate_field(f_ulat,field_t,type_real,llm, name='ulat')
82       CALL allocate_field(f_p,field_t,type_real,llm+1, name='p')
83       CALL allocate_field(f_pk,field_t,type_real,llm, name='pk')
[217]84       CALL init_pack_before ! Compute physics_inout%ngrid and offsets used by pack/unpack
[214]85       CALL init_physics_dcmip
[217]86       CALL init_pack_after ! Defines Ai, lon, lat in physics_inout
[196]87       phys_type = phys_DCMIP
[726]88!$OMP END PARALLEL
89
[381]90    CASE ('dcmip2016')
[726]91
92!$OMP PARALLEL
[381]93       CALL allocate_field(f_dulon,field_t,type_real,llm, name='dulon')
94       CALL allocate_field(f_dulat,field_t,type_real,llm, name='dulat')
95       CALL allocate_field(f_temp,field_t,type_real,llm, name='temp')
[481]96       CALL allocate_field(f_ulon,field_t,type_real,llm, name='ulon')
97       CALL allocate_field(f_ulat,field_t,type_real,llm, name='ulat')
98       CALL allocate_field(f_p,field_t,type_real,llm+1, name='p')
99       CALL allocate_field(f_pk,field_t,type_real,llm, name='pk')
[381]100       CALL init_pack_before ! Compute physics_inout%ngrid and offsets used by pack/unpack
101       CALL init_physics_dcmip2016
102       CALL init_pack_after ! Defines Ai, lon, lat in physics_inout
103       phys_type = phys_DCMIP2016
[726]104!$OMP END PARALLEL
105
[170]106    CASE DEFAULT
[196]107       IF(is_mpi_root) PRINT*, 'init_physics : Bad selector for variable physics <',&
[347]108            TRIM(physics_type), '> options are <none>, <held_suarez>, <Lebonnois2012>, <dcmip>', &
109                                '<phys_lmdz_generic>, <phys_external>'
[170]110       STOP
[81]111    END SELECT
[170]112
[726]113!$OMP PARALLEL
[714]114    CALL allocate_field(f_du_phys,field_u,type_real,llm, name='du_phys')
115
[214]116    IF(is_mpi_root) PRINT *, 'phys_type = ',phys_type
[726]117!$OMP END PARALLEL
[81]118  END SUBROUTINE init_physics
119
[714]120  SUBROUTINE zero_du_phys()
121    REAL(rstd), DIMENSION(:,:), POINTER :: du
122    INTEGER :: ind
123    DO ind=1,ndomain
124       IF (.NOT. assigned_domain(ind)) CYCLE
125       CALL swap_dimensions(ind)
126       CALL swap_geometry(ind)
127       du=f_du_phys(ind)
128       du(:,ll_begin:ll_end) = 0.
129    END DO
130  END SUBROUTINE zero_du_phys
131
132  SUBROUTINE add_du_phys(coef, f_u)
133    REAL(rstd), INTENT(IN) :: coef  ! -1 before physics, +1 after physics
134    TYPE(t_field),POINTER :: f_u(:) ! velocity field before/after call to physics
135    REAL(rstd), DIMENSION(:,:), POINTER :: u, du
136    INTEGER :: ind
137    DO ind=1,ndomain
138       IF (.NOT. assigned_domain(ind)) CYCLE
139       CALL swap_dimensions(ind)
140       CALL swap_geometry(ind)
141       du=f_du_phys(ind)
142       u=f_u(ind)
143       du(:,ll_begin:ll_end) = du(:,ll_begin:ll_end) + coef*u(:,ll_begin:ll_end)
144    END DO
145  END SUBROUTINE add_du_phys
146
[327]147  SUBROUTINE physics(it,f_phis, f_ps, f_theta_rhodz, f_ue, f_wflux, f_q)
148    USE physics_lmdz_generic_mod, ONLY : physics_lmdz_generic => physics
[347]149    USE physics_external_mod, ONLY : physics_external => physics
[213]150    USE physics_dcmip_mod, ONLY : write_physics_dcmip => write_physics
[381]151    USE physics_dcmip2016_mod, ONLY : write_physics_dcmip2016 => write_physics
[170]152    USE etat0_heldsz_mod
[325]153    USE etat0_venus_mod, ONLY : phys_venus => physics
[99]154    INTEGER, INTENT(IN)   :: it
[81]155    TYPE(t_field),POINTER :: f_phis(:)
156    TYPE(t_field),POINTER :: f_ps(:)
157    TYPE(t_field),POINTER :: f_theta_rhodz(:)
158    TYPE(t_field),POINTER :: f_ue(:)
[327]159    TYPE(t_field),POINTER :: f_wflux(:)
[81]160    TYPE(t_field),POINTER :: f_q(:)
[196]161
[149]162    LOGICAL:: firstcall,lastcall
[196]163    INTEGER :: ind
[213]164    TYPE(t_physics_inout) :: args
[170]165
[714]166    IF(MOD(it,itau_physics)==0 .AND. phys_type/=phys_none) THEN
167
168       ! as a result of the the two calls to add_du_phys,
169       ! du_phys increases by u(after physics) - u (before physics)
170       CALL add_du_phys(-1., f_ue)
171
[213]172       SELECT CASE(phys_type)
173       CASE(phys_HS94)
174          CALL held_suarez(f_ps,f_theta_rhodz,f_ue) 
[327]175       CASE (phys_lmdz_generic)
176         CALL physics_lmdz_generic(it ,f_phis, f_ps, f_theta_rhodz, f_ue, f_wflux, f_q)
[347]177       CASE (phys_external)
178         CALL physics_external(it ,f_phis, f_ps, f_theta_rhodz, f_ue, f_wflux, f_q)
[325]179       CASE(phys_LB2012)
180          CALL phys_venus(f_ps,f_theta_rhodz,f_ue) 
[213]181       CASE DEFAULT
[214]182          CALL physics_column(it, f_phis, f_ps, f_theta_rhodz, f_ue, f_q)
[213]183       END SELECT
[149]184
[213]185       CALL transfert_request(f_theta_rhodz,req_i0)
186       CALL transfert_request(f_ue,req_e0_vect)
187       CALL transfert_request(f_q,req_i0)
[714]188
189       CALL add_du_phys(1., f_ue)
[213]190    END IF
[149]191
[213]192    IF (mod(it,itau_out)==0 ) THEN
[714]193       CALL write_physics_tendencies
194       CALL zero_du_phys
[213]195       SELECT CASE(phys_type)
196       CASE (phys_DCMIP)
197          CALL write_physics_dcmip
[381]198       CASE (phys_DCMIP2016)
199          CALL write_physics_dcmip2016
[213]200       END SELECT
201    END IF
202   
203  END SUBROUTINE physics
204
[714]205  SUBROUTINE write_physics_tendencies
206    USE observable_mod, ONLY : f_buf_ulon, f_buf_ulat
207    USE wind_mod
208    USE output_field_mod
209    CALL transfert_request(f_du_phys,req_e1_vect)
210    CALL un2ulonlat(f_du_phys, f_buf_ulon, f_buf_ulat, (1./(dt*itau_out)))
211    CALL output_field("dulon_phys",f_buf_ulon)
212    CALL output_field("dulat_phys",f_buf_ulat)
213  END SUBROUTINE write_physics_tendencies
214   
[214]215  SUBROUTINE physics_column(it, f_phis, f_ps, f_theta_rhodz, f_ue, f_q)
[213]216    USE physics_dcmip_mod, ONLY : full_physics_dcmip => full_physics
[381]217    USE physics_dcmip2016_mod, ONLY : full_physics_dcmip2016 => full_physics
[295]218    USE theta2theta_rhodz_mod
[281]219    USE mpipara
[481]220    USE checksum_mod
[213]221    TYPE(t_field),POINTER :: f_phis(:)
222    TYPE(t_field),POINTER :: f_ps(:)
223    TYPE(t_field),POINTER :: f_theta_rhodz(:)
224    TYPE(t_field),POINTER :: f_ue(:)
225    TYPE(t_field),POINTER :: f_q(:)
226    REAL(rstd),POINTER :: phis(:)
227    REAL(rstd),POINTER :: ps(:)
[295]228    REAL(rstd),POINTER :: temp(:,:)
[213]229    REAL(rstd),POINTER :: ue(:,:)
230    REAL(rstd),POINTER :: dulon(:,:)
231    REAL(rstd),POINTER :: dulat(:,:)
232    REAL(rstd),POINTER :: q(:,:,:)
[481]233    REAL(rstd),POINTER :: p(:,:)
234    REAL(rstd),POINTER :: pk(:,:)
235    REAL(rstd),POINTER :: ulon(:,:)
236    REAL(rstd),POINTER :: ulat(:,:)
[213]237    INTEGER :: it, ind
238
[295]239    CALL theta_rhodz2temperature(f_ps,f_theta_rhodz,f_temp)
[381]240   
[213]241    DO ind=1,ndomain
242       IF (.NOT. assigned_domain(ind)) CYCLE
243       CALL swap_dimensions(ind)
244       CALL swap_geometry(ind)
245       phis=f_phis(ind)
246       ps=f_ps(ind)
[295]247       temp=f_temp(ind)
[213]248       ue=f_ue(ind)
249       q=f_q(ind)
[481]250       p=f_p(ind)
251       pk=f_pk(ind)
252       ulon=f_ulon(ind)
253       ulat=f_ulat(ind)
254       CALL pack_physics(pack_info(ind), phis, ps, temp, ue, q, p, pk, ulon, ulat)
[213]255    END DO
256
257    SELECT CASE(phys_type)
258    CASE (phys_DCMIP)
[481]259       IF (is_omp_level_master) CALL full_physics_dcmip
[381]260    CASE (phys_DCMIP2016)
[481]261       IF (is_omp_level_master) CALL full_physics_dcmip2016
[281]262    CASE DEFAULT
[481]263       IF(is_master) PRINT *,'Internal error : illegal value of phys_type', phys_type
[281]264       STOP
[196]265    END SELECT
[170]266
[213]267    DO ind=1,ndomain
268       IF (.NOT. assigned_domain(ind)) CYCLE
269       CALL swap_dimensions(ind)
270       CALL swap_geometry(ind)
271       ps=f_ps(ind)
[295]272       temp=f_temp(ind)
[213]273       q=f_q(ind)
274       dulon=f_dulon(ind)
275       dulat=f_dulat(ind)
[295]276       CALL unpack_physics(pack_info(ind), ps, temp, q, dulon, dulat)
[213]277    END DO
[481]278   
[295]279    CALL temperature2theta_rhodz(f_ps,f_temp,f_theta_rhodz)
[170]280
[213]281    ! Transfer dulon, dulat
282    CALL transfert_request(f_dulon,req_i0)
283    CALL transfert_request(f_dulat,req_i0)
284
285    DO ind=1,ndomain
286       IF (.NOT. assigned_domain(ind)) CYCLE
287       CALL swap_dimensions(ind)
288       CALL swap_geometry(ind)
289       ue=f_ue(ind)
290       dulon=f_dulon(ind)
291       dulat=f_dulat(ind)
292       CALL compute_update_velocity(dulon, dulat, ue)
293    END DO
294
[214]295  END SUBROUTINE physics_column
[213]296
[481]297  SUBROUTINE pack_physics(info, phis, ps, temp, ue, q, p, pk, ulon, ulat )
[213]298    USE wind_mod
299    USE pression_mod
300    USE theta2theta_rhodz_mod
[381]301    USE exner_mod
[213]302    TYPE(t_pack_info) :: info
303    REAL(rstd) :: phis(iim*jjm)
304    REAL(rstd) :: ps(iim*jjm)
[295]305    REAL(rstd) :: temp(iim*jjm,llm)
[381]306    REAL(rstd) :: pks(iim*jjm)
307    REAL(rstd) :: pk(iim*jjm,llm)
[213]308    REAL(rstd) :: ue(3*iim*jjm,llm)
309    REAL(rstd) :: q(iim*jjm,llm,nqtot)
310
311    REAL(rstd) :: p(iim*jjm,llm+1)
[584]312    REAL(rstd) :: uc(iim*jjm,llm,3)
[213]313    REAL(rstd) :: ulon(iim*jjm,llm)
314    REAL(rstd) :: ulat(iim*jjm,llm)
315
[295]316!$OMP BARRIER
[213]317    CALL compute_pression(ps,p,0)
[295]318!$OMP BARRIER
[381]319    CALL compute_exner(ps,p,pks,pk,0) 
320!$OMP BARRIER
[213]321    CALL compute_wind_centered(ue,uc)
322    CALL compute_wind_centered_lonlat_compound(uc, ulon, ulat)
[481]323!$OMP BARRIER
324    IF (is_omp_level_master) THEN
325      CALL pack_domain(info, phis, physics_inout%phis)
326      CALL pack_domain(info, p, physics_inout%p)
327      CALL pack_domain(info, pk, physics_inout%pk)
328      CALL pack_domain(info, Temp, physics_inout%Temp)
329      CALL pack_domain(info, ulon, physics_inout%ulon)
330      CALL pack_domain(info, ulat, physics_inout%ulat)
331      CALL pack_domain(info, q, physics_inout%q)
332    ENDIF
333!$OMP BARRIER
[213]334  END SUBROUTINE pack_physics
335
[295]336  SUBROUTINE unpack_physics(info, ps,temp, q, dulon, dulat)
[213]337    USE theta2theta_rhodz_mod
338    TYPE(t_pack_info) :: info
339    REAL(rstd) :: ps(iim*jjm)
[295]340    REAL(rstd) :: temp(iim*jjm,llm)
[213]341    REAL(rstd) :: q(iim*jjm,llm,nqtot)
342    REAL(rstd) :: dulon(iim*jjm,llm)
343    REAL(rstd) :: dulat(iim*jjm,llm)
344
345    REAL(rstd) :: dq(iim*jjm,llm,nqtot)
346    REAL(rstd) :: dTemp(iim*jjm,llm)
[481]347
348!$OMP BARRIER
349    IF (is_omp_level_master) THEN
350      CALL unpack_domain(info, dulon, physics_inout%dulon)
351      CALL unpack_domain(info, dulat, physics_inout%dulat)
352      CALL unpack_domain(info, dq, physics_inout%dq)
353      CALL unpack_domain(info, Temp, physics_inout%Temp)
354      CALL unpack_domain(info, dTemp, physics_inout%dTemp)
355      q = q + physics_inout%dt_phys * dq
356      Temp = Temp + physics_inout%dt_phys * dTemp
357    ENDIF
358!$OMP BARRIER
359
[295]360!    CALL compute_temperature2theta_rhodz(ps,Temp,theta_rhodz,0)
[213]361  END SUBROUTINE unpack_physics
362
363  SUBROUTINE compute_update_velocity(dulon, dulat, ue)
364    USE wind_mod
365    REAL(rstd) :: dulon(iim*jjm,llm)
366    REAL(rstd) :: dulat(iim*jjm,llm)
367    REAL(rstd) :: ue(3*iim*jjm,llm)
[584]368    REAL(rstd) :: duc(iim*jjm,llm,3)
[213]369    REAL(rstd) :: dt2, due
370    INTEGER :: i,j,ij,l
371    ! Reconstruct wind tendencies at edges and add to normal wind
372    CALL compute_wind_centered_from_lonlat_compound(dulon,dulat,duc)
373    dt2=.5*physics_inout%dt_phys
[481]374    DO l=ll_begin,ll_end
[213]375      DO j=jj_begin,jj_end
376        DO i=ii_begin,ii_end
377          ij=(j-1)*iim+i
[584]378          due = sum( (duc(ij,l,:) + duc(ij+t_right,l,:))*ep_e(ij+u_right,:) )
[213]379          ue(ij+u_right,l) = ue(ij+u_right,l) + dt2*due
380
[584]381          due = sum( (duc(ij,l,:) + duc(ij+t_lup,l,:))*ep_e(ij+u_lup,:) )
[213]382          ue(ij+u_lup,l)=ue(ij+u_lup,l) + dt2*due
383
[584]384          due = sum( (duc(ij,l,:) + duc(ij+t_ldown,l,:))*ep_e(ij+u_ldown,:) )
[213]385          ue(ij+u_ldown,l)=ue(ij+u_ldown,l) + dt2*due
386        ENDDO
387      ENDDO
388    ENDDO
389  END SUBROUTINE compute_update_velocity
390
[81]391END MODULE physics_mod
Note: See TracBrowser for help on using the repository browser.