source: codes/icosagcm/trunk/src/physics/physics.f90 @ 886

Last change on this file since 886 was 871, checked in by ymipsl, 5 years ago

experimental : add smooth physics tendency for external physics.

Activated with param :

phys_smooth_tendency=y

To be tested...

YM

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