source: codes/icosagcm/trunk/src/initial/etat0_heldsz.f90 @ 548

Last change on this file since 548 was 548, checked in by dubos, 7 years ago

trunk : reorganize source tree

File size: 7.4 KB
RevLine 
[170]1MODULE etat0_heldsz_mod
2  USE icosa
3  IMPLICIT NONE
4  PRIVATE
[544]5  SAVE
[149]6
[170]7  TYPE(t_field),POINTER :: f_theta_eq(:)
8  TYPE(t_field),POINTER :: f_theta(:)
9
[186]10  REAL(rstd),ALLOCATABLE,SAVE :: knewt_t(:),kfrict(:)
11!$OMP THREADPRIVATE(knewt_t,kfrict)
[170]12  LOGICAL, SAVE :: done=.FALSE.
[186]13!$OMP THREADPRIVATE(done)
[170]14
[544]15  REAL(rstd),SAVE :: p0,teta0,ttp,delt_y,delt_z,eps
16!$OMP THREADPRIVATE(p0,teta0,ttp,delt_y,delt_z,eps)
[170]17
[186]18  REAL(rstd),SAVE :: knewt_g, k_f,k_c_a,k_c_s
19!$OMP THREADPRIVATE(knewt_g, k_f,k_c_a,k_c_s)
20
[544]21  PUBLIC :: init_etat0, etat0, held_suarez
[170]22 
[149]23CONTAINS
[170]24
[149]25  SUBROUTINE test_etat0_heldsz
[170]26    USE kinetic_mod
[149]27    TYPE(t_field),POINTER :: f_ps(:)
28    TYPE(t_field),POINTER :: f_phis(:)
29    TYPE(t_field),POINTER :: f_theta_rhodz(:)
30    TYPE(t_field),POINTER :: f_u(:)
31    TYPE(t_field),POINTER :: f_q(:)
32    TYPE(t_field),POINTER :: f_Ki(:)
[170]33
[149]34    REAL(rstd),POINTER :: Ki(:,:)
35    INTEGER :: ind
[170]36
[149]37    CALL allocate_field(f_ps,field_t,type_real)
38    CALL allocate_field(f_phis,field_t,type_real)
[485]39    CALL allocate_field(f_theta_rhodz,field_t,type_real,llm,2)
[149]40    CALL allocate_field(f_u,field_u,type_real,llm)
41    CALL allocate_field(f_Ki,field_t,type_real,llm)
[170]42
[149]43    CALL etat0(f_ps,f_phis,f_theta_rhodz,f_u, f_q)
44    CALL kinetic(f_u,f_Ki)
45
46    CALL writefield('ps',f_ps)
47    CALL writefield('theta',f_theta_rhodz)
48  END SUBROUTINE test_etat0_heldsz
[170]49
[544]50  SUBROUTINE init_etat0
51    p0=1e5 ! default value of initial surface pressure as in H&S paper
52    ! p0=101080 for CMIP5 aquaplanets, cf LMDZ5 ini_aqua
53    CALL getin('heldsz_p0',p0)
54  END SUBROUTINE init_etat0
55
[149]56  SUBROUTINE etat0(f_ps,f_phis,f_theta_rhodz,f_u, f_q)
[170]57    USE theta2theta_rhodz_mod
58    IMPLICIT NONE
[149]59    TYPE(t_field),POINTER :: f_ps(:)
60    TYPE(t_field),POINTER :: f_phis(:)
61    TYPE(t_field),POINTER :: f_theta_rhodz(:)
62    TYPE(t_field),POINTER :: f_u(:)
63    TYPE(t_field),POINTER :: f_q(:)
[170]64
[149]65    REAL(rstd),POINTER :: ps(:)
66    REAL(rstd),POINTER :: phis(:)
[485]67    REAL(rstd),POINTER :: theta_rhodz(:,:,:)
[149]68    REAL(rstd),POINTER :: u(:,:)
69    REAL(rstd),POINTER :: q(:,:,:)
[170]70    REAL(rstd),POINTER :: theta_eq(:,:) 
71    REAL(rstd),POINTER :: theta(:,:) 
72
[149]73    INTEGER :: ind
74
[170]75    CALL Init_Teq
[149]76    DO ind=1,ndomain
[186]77       IF (.NOT. assigned_domain(ind)) CYCLE
[170]78       CALL swap_dimensions(ind)
79       CALL swap_geometry(ind)
80
81       theta_eq=f_theta_eq(ind) 
[347]82       CALL compute_Teq(lat_i,theta_eq) ! FIXME : already done by Init_Teq
[170]83
84       ps=f_ps(ind)
85       phis=f_phis(ind)
86       u=f_u(ind)
[544]87       ps(:)=p0
[170]88       phis(:)=0.
89       u(:,:)=0
90
91       theta_rhodz=f_theta_rhodz(ind)
92       theta=f_theta(ind)
93       CALL compute_etat0_heldsz(theta_eq,theta)
[485]94       CALL compute_theta2theta_rhodz(ps,theta,theta_rhodz(:,:,1),1)
[359]95       IF(nqtot>0) THEN
96          q=f_q(ind)
97          q(:,:,1)=1e-2
98          IF(nqtot>1) q(:,:,2)=0
99          IF(nqtot>2) q(:,:,3:)=1e-2
100       END IF
[149]101    ENDDO
102  END SUBROUTINE etat0
103
[170]104  SUBROUTINE init_Teq
105    USE disvert_mod, ONLY : ap,bp
106    REAL(rstd),POINTER :: clat(:) 
107    REAL(rstd),POINTER :: theta_eq(:,:) 
108    REAL(rstd) :: zsig
109    INTEGER :: ind, l
[149]110
[170]111    IF(.NOT.done) THEN
112       done = .TRUE.
113       
114       CALL allocate_field(f_theta,field_t,type_real,llm)
115       CALL allocate_field(f_theta_eq,field_t,type_real,llm)
116       ALLOCATE(knewt_t(llm)); ALLOCATE( kfrict(llm)) 
117
118       k_f=1.                !friction
119       CALL getin('k_j',k_f)
120       k_f=1./(daysec*k_f)
121       k_c_s=4.  !cooling surface
122       CALL getin('k_c_s',k_c_s)
123       k_c_s=1./(daysec*k_c_s)
124       k_c_a=40. !cooling free atm
125       CALL getin('k_c_a',k_c_a)
126       k_c_a=1./(daysec*k_c_a)
127       ! Constants for Teta equilibrium profile
128       teta0=315.     ! mean Teta (S.H. 315K)
129       CALL getin('teta0',teta0)
130       ttp=200.       ! Tropopause temperature (S.H. 200K)
131       CALL getin('ttp',ttp)
132       eps=0.         ! Deviation to N-S symmetry(~0-20K)
133       CALL getin('eps',eps)
134       delt_y=60.     ! Merid Temp. Gradient (S.H. 60K)
135       CALL getin('delt_y',delt_y)
136       delt_z=10.     ! Vertical Gradient (S.H. 10K)
137       CALL getin('delt_z',delt_z)
138
139       !-----------------------------------------------------------
140       knewt_g=k_c_a 
141       DO l=1,llm
142          zsig=ap(l)/preff+bp(l)
143          knewt_t(l)=(k_c_s-k_c_a)*MAX(0.,(zsig-0.7)/0.3) 
144          kfrict(l)=k_f*MAX(0.,(zsig-0.7)/0.3) 
145       ENDDO
146
147       DO ind=1,ndomain
[186]148          IF (.NOT. assigned_domain(ind)) CYCLE
[170]149          CALL swap_dimensions(ind)
150          CALL swap_geometry(ind)
151          theta_eq=f_theta_eq(ind)
[286]152          CALL compute_Teq(lat_i,theta_eq)
[170]153       ENDDO
154
155    ELSE
156       PRINT *, 'Init_Teq called twice'
157       CALL ABORT
158    END IF
159
160  END SUBROUTINE init_Teq
161
[286]162  SUBROUTINE compute_Teq(lat,theta_eq)
[170]163    USE disvert_mod
[286]164    REAL(rstd),INTENT(IN) :: lat(iim*jjm)
[170]165    REAL(rstd),INTENT(OUT) :: theta_eq(iim*jjm,llm) 
166
[286]167    REAL(rstd) :: r, zsig, ddsin, tetastrat, tetajl
[170]168    INTEGER :: i,j,l,ij
169
[149]170    DO l=1,llm
171       zsig=ap(l)/preff+bp(l)
172       tetastrat=ttp*zsig**(-kappa)
[170]173       DO j=jj_begin-1,jj_end+1
174          DO i=ii_begin-1,ii_end+1
[149]175             ij=(j-1)*iim+i
[286]176             ddsin=SIN(lat(ij)) 
[170]177             tetajl=teta0-delt_y*ddsin*ddsin+eps*ddsin &
178                  -delt_z*(1.-ddsin*ddsin)*log(zsig)
179             theta_eq(ij,l)=MAX(tetajl,tetastrat) 
180          ENDDO
[149]181       ENDDO
[170]182    ENDDO
183  END SUBROUTINE compute_Teq
[149]184
[170]185  SUBROUTINE compute_etat0_heldsz(theta_eq, theta)
186    USE disvert_mod
187    REAL(rstd),INTENT(IN) :: theta_eq(iim*jjm,llm) 
188    REAL(rstd),INTENT(OUT) :: theta(iim*jjm,llm) 
[149]189
[170]190    REAL(rstd) :: r  ! random number
191    INTEGER :: i,j,l,ij
192
193    DO l=1,llm
194       DO j=jj_begin-1,jj_end+1
195          DO i=ii_begin-1,ii_end+1
196             ij=(j-1)*iim+i
197             CALL RANDOM_NUMBER(r); r = 0.0 
198             theta(ij,l)=theta_eq(ij,l)*(1.+0.0005*r)
199          ENDDO
[149]200       ENDDO
[170]201    ENDDO
[149]202
203  END SUBROUTINE compute_etat0_heldsz
204
205
[170]206  SUBROUTINE held_suarez(f_ps,f_theta_rhodz,f_u) 
[149]207    TYPE(t_field),POINTER :: f_theta_rhodz(:)
208    TYPE(t_field),POINTER :: f_u(:)
209    TYPE(t_field),POINTER :: f_ps(:)
[494]210    REAL(rstd),POINTER :: theta_rhodz(:,:,:)
[149]211    REAL(rstd),POINTER :: u(:,:)
212    REAL(rstd),POINTER :: ps(:)
[170]213    REAL(rstd),POINTER :: theta_eq(:,:)
214    REAL(rstd),POINTER :: theta(:,:)
[149]215    REAL(rstd),POINTER :: clat(:)
216    INTEGER::ind
217
218    DO ind=1,ndomain
[186]219       IF (.NOT. assigned_domain(ind)) CYCLE
[170]220       CALL swap_dimensions(ind)
221       CALL swap_geometry(ind)
222       theta_rhodz=f_theta_rhodz(ind)
223       u=f_u(ind)
224       ps=f_ps(ind) 
225       theta_eq=f_theta_eq(ind) 
226       theta=f_theta(ind) 
[494]227       CALL compute_heldsz(ps,theta_eq,lat_i, theta_rhodz(:,:,1),u, theta) 
[149]228    ENDDO
[170]229  END SUBROUTINE held_suarez
[149]230
[286]231  SUBROUTINE compute_heldsz(ps,theta_eq,lat, theta_rhodz,u, theta) 
[170]232    USE theta2theta_rhodz_mod
233    REAL(rstd),INTENT(IN)    :: ps(iim*jjm) 
234    REAL(rstd),INTENT(IN)    :: theta_eq(iim*jjm,llm) 
[286]235    REAL(rstd),INTENT(IN)    :: lat(iim*jjm) 
[170]236    REAL(rstd),INTENT(INOUT) :: theta_rhodz(iim*jjm,llm)
237    REAL(rstd),INTENT(INOUT) :: u(3*iim*jjm,llm)
238    REAL(rstd),INTENT(OUT)   :: theta(iim*jjm,llm) 
[149]239
[170]240    INTEGER :: i,j,l,ij
241
242    CALL compute_theta_rhodz2theta(ps,theta_rhodz,theta,1)
[149]243    DO l=1,llm
[170]244       DO j=jj_begin-1,jj_end+1
245          DO i=ii_begin-1,ii_end+1
246             ij=(j-1)*iim+i
247             theta(ij,l)=theta(ij,l) - dt*(theta(ij,l)-theta_eq(ij,l))* &
[286]248                  (knewt_g+knewt_t(l)*COS(lat(ij))**4 )
[170]249          ENDDO
250       ENDDO
251    ENDDO
252    CALL compute_theta2theta_rhodz(ps,theta,theta_rhodz,1)
[149]253
[170]254    Do l=1,llm
255       u(:,l)=u(:,l)*(1.-dt*kfrict(l))
256    END DO
[149]257
[170]258  END SUBROUTINE compute_heldsz
[149]259
260END MODULE etat0_heldsz_mod
Note: See TracBrowser for help on using the repository browser.