SURFEX  V8_0
Surfex V8_0 release
 All Classes Files Functions Variables
init_slope_param.F90
Go to the documentation of this file.
1 !SFX_LIC Copyright 1994-2014 CNRS, Meteo-France and Universite Paul Sabatier
2 !SFX_LIC This is part of the SURFEX software governed by the CeCILL-C licence
3 !SFX_LIC version 1. See LICENSE, CeCILL-C_V1-en.txt and CeCILL-C_V1-fr.txt
4 !SFX_LIC for details. version 1.
5 SUBROUTINE init_slope_param (UG, &
6  pzs,ki,plat)
7 !
8 !!**** *INIT_SLOPE_PARAM
9 !! Compute physiographic field necessary to account for
10 !! slope and aspect effects on short-wave radiations
11 !!
12 !! PURPOSE
13 !! -------
14 !!
15 !! METHOD
16 !! ------
17 !!
18 !
19 !! EXTERNAL
20 !! --------
21 !!
22 !! IMPLICIT ARGUMENTS
23 !! ------------------
24 !!
25 !! REFERENCE
26 !! ---------
27 !!
28 !!
29 !! AUTHOR
30 !! ------
31 !!
32 !! V. Vionnet Meteo-France
33 !!
34 !! MODIFICATION
35 !! ------------
36 !!
37 !! Original 04/11
38 !!
39 !!
40 !! Modifications Matthieu Lafaysse 04/14 :
41 !! * Computations of XSLOPANG, XSLOPAZI and XSURF_TRIANGLE in this routine (optimization)
42 !! * Call to GET_GRID_DIM moved in get_size_parallel to initialize NIX and NIY
43 !! * Modifications linked to parallelization : gather full domain on all MPI threads
44 !! * Solar azimuth is now counted from North clockwise : N --> 0 ; E --> pi/2 ; S --> pi ; W --> -pi/2
45 !! for consistency with solar azimuth.
46 !----------------------------------------------------------------------------
47 !
48 !* 0. DECLARATION
49 ! -----------
50 !
51 !
53 !
54 USE modi_get_mesh_dim
55 !
56 USE modd_surfex_mpi, ONLY : nrank, npio, nproc, ncomm, nsize, nindex, nsize_task
57 
59 !
60 IMPLICIT NONE
61 !
62 #ifdef SFX_MPI
63 include "mpif.h"
64 #endif
65 
66 !* 0.1 Declaration of arguments
67 ! ------------------------
68 !
69 !
70 TYPE(surf_atm_grid_t), INTENT(INOUT) :: ug
71 !
72 INTEGER, INTENT(IN) :: ki ! number of points
73 REAL, DIMENSION(KI), INTENT(IN) :: pzs ! orography of this MPI thread (or total domain if Open MP)
74 REAL,DIMENSION(:),INTENT(IN):: plat ! latitudes
75 !
76 !
77 !
78 !* 0.2 Declaration of local variables
79 ! ------------------------------
80 !
81 LOGICAL :: grect ! true when grid is rectangular
82 
83 INTEGER :: jx ! loop counter
84 INTEGER :: jy ! loop counter
85 
86 REAL, DIMENSION(:),ALLOCATABLE :: zzs1d_full !orography of total domain
87 REAL, DIMENSION(:,:), ALLOCATABLE :: zzs ! orography in a 2D array
88 
89 REAL,DIMENSION(:), ALLOCATABLE :: zdx ! grid mesh size in x direction
90 REAL,DIMENSION(:), ALLOCATABLE :: zdy ! grid mesh size in y direction
91 
92 REAL, PARAMETER :: xpi=4.*atan(1.) ! Pi
93 INTEGER, PARAMETER :: jphext = 1 ! number of points around the physical domain
94 
95 REAL :: zdzsdx ! slope in X and Y direction
96 REAL :: zdzsdy ! of a triangle surface
97 
98 INTEGER :: iib, iie, ijb, ije
99 INTEGER :: ji, jj
100 INTEGER :: jt ! loop counter (triangles)
101 INTEGER :: infompi
102 INTEGER,DIMENSION(:),ALLOCATABLE::idispls
103 INTEGER::jpoint,jproc
104 INTEGER::irank,inextrank,ipos
105 INTEGER::iindy
106 
107 !-------------------------------------------------------------------------------
108 !
109 !* 1.1 Gets the geometry of the grid
110 ! -----------------------------
111 !
112 
113 
114 ! Toutes les threads MPI doivent connaître le champ d'altitude complet
115 ALLOCATE(zzs1d_full(nix*niy))
116 
117 #ifdef SFX_MPI
118 
119 IF (nproc>1) THEN
120 
121  ALLOCATE(idispls(0:nproc-1))
122  idispls(0)=0
123 
124  !IRANK est le rang du thread associé au 1er point
125  ipos=1
126  irank=nindex(ipos)
127  idispls(irank)=0
128 
129  ! Attention cette méthode ne marche que si NINDEX est continu (découpage linéaire)
130  DO jproc=1,nproc-1
131  !INEXTRANK est le rang du thread suivant : on décale IPOS du nb de points affectés au thread précedent
132  ! et on ajoute à IDISPLS(INEXTRANK) l'espace correspondant
133  ipos=ipos+nsize_task(irank)
134  inextrank=nindex(ipos)
135  idispls(inextrank)=idispls(irank)+nsize_task(irank)*kind(pzs)/4
136  irank=inextrank
137  END DO
138 
139  CALL mpi_allgatherv(pzs,SIZE(pzs)*kind(pzs)/4,mpi_real,zzs1d_full, &
140  nsize_task(:)*kind(pzs)/4,idispls,mpi_real,ncomm,infompi)
141 
142 ELSE
143  zzs1d_full=pzs
144 ENDIF
145 
146 #else
147  zzs1d_full=pzs
148 #endif
149 
150 nnx=nix+2
151 nny=niy+2
152 
153 !
154 
155 !* 1.2 Grid dimension (meters)
156 ! -----------------------
157 !
158 ALLOCATE(zdx(nix*niy))
159 ALLOCATE(zdy(nix*niy))
160 
161 IF (nrank==npio) THEN
162 
163  CALL get_mesh_dim(ug%CGRID,SIZE(ug%XGRID_FULL_PAR),nix*niy,ug%XGRID_FULL_PAR,zdx,zdy,ug%XMESH_SIZE)
164 
165 ENDIF
166 
167 #ifdef SFX_MPI
168 IF (nproc>1) THEN
169  CALL mpi_bcast(zdx,SIZE(zdx)*kind(zdx)/4,mpi_real,npio,ncomm,infompi)
170  CALL mpi_bcast(zdy,SIZE(zdy)*kind(zdy)/4,mpi_real,npio,ncomm,infompi)
171 END IF
172 #endif
173 !
174 !-------------------------------------------------------------------------------
175 !
176 !* 2. If grid is not rectangular, nothing is done
177 ! -------------------------------------------
178 !
179 IF (SIZE(zzs1d_full) /= nix * niy) stop "BIG PROBLEM WITH SIZE"
180 !
181 !-------------------------------------------------------------------------------
182 !
183 !* 3.1 Grid rectangular: orography is put in a 2D array
184 ! ------------------------------------------------
185 !
186 ALLOCATE(zzs(nix,niy))
187 ALLOCATE(xzsl(nnx,nny))
188 !
189 !RJ: next one does not work with NPROC>4
190 !RJ 'Fortran runtime error: Index '13' of dimension 1 of array 'plat' above upper bound of 12'
191 ! 2d grid should be increasing in latitude
192 lrevertgrid=(plat(1)>plat(1+nix))
193 
194 IF (lrevertgrid) THEN
195  DO jy=1,niy
196  iindy=niy-jy+1
197  DO jx=1,nix
198  zzs(jx,iindy) = zzs1d_full( jx + (jy-1)*nix )
199  END DO
200  END DO
201 ELSE
202  DO jy=1,niy
203  DO jx=1,nix
204  zzs(jx,jy) = zzs1d_full( jx + (jy-1)*nix )
205  END DO
206  END DO
207 ENDIF
208 
209 xzsl(2:nnx-1,2:nny-1) = zzs(:,:)
210 xzsl(1,:) = xzsl(2,:)
211 xzsl(nnx,:) = xzsl(nnx-1,:)
212 xzsl(:,1) = xzsl(:,2)
213 xzsl(:,nny) = xzsl(:,nny-1)
214 
215 !------------------------------------------------------------------------------------------
216 !
217 !* 3.2. Orography of SW corner of grid meshes
218 ! -------------------------------------
219 !
220 ALLOCATE(xzs_xy(nnx,nny))
221 xzs_xy(2:nnx,2:nny) = 0.25*(xzsl(2:nnx,2:nny) +xzsl(1:nnx-1,2:nny) +&
222  xzsl(2:nnx,1:nny-1)+xzsl(1:nnx-1,1:nny-1))
223 !
224 xzs_xy(1,:) = xzs_xy(2,:)
225 xzs_xy(:,1) = xzs_xy(:,2)
226 !
227 !* 3.3 Initialize Grid meshes
228 ! -----------
229 !
230 ALLOCATE(xxhat(nnx))
231 ALLOCATE(xyhat(nny))
232 
233 xxhat(1)=zdx(1)
234 xyhat(1)=zdy(1)
235 DO jx=2,nnx
236  xxhat(jx) = xxhat(jx-1)+zdx(jx)
237 END DO
238 DO jy=2,nny
239  xyhat(jy) = xyhat(jy-1)+zdy(jy)
240 END DO
241 
242 DEALLOCATE(zzs)
243 
244 !-------------------------------------------------------------------------------
245 !
246 !* 4. Compute slope angles
247 ! -------------------
248 
249 iib= 1+jphext
250 iie=SIZE(xxhat)-jphext
251 ijb=1+jphext
252 ije=SIZE(xyhat)-jphext
253 
254 ALLOCATE(xslopang(nnx,nny,4))
255 ALLOCATE(xslopazi(nnx,nny,4))
256 ALLOCATE(xsurf_triangle(nnx,nny,4))
257 
258 ! 4.1 Loop on 4 triangles
259 !
260 !------------------------------------------------------------------------------------------
261 DO jt=1,4
262 !
263  DO jj=ijb,ije
264  DO ji=iib,iie
265 !
266 !-------------------------------------------------------------------------------
267 !
268 !* 4.2 Compute local slope
269 ! --------------------------------------------
270 !
271 !* slopes in x and y
272 !
273  SELECT CASE (jt)
274  CASE (1)
275  zdzsdx=( 2.* xzsl(ji,jj) &
276  - (xzs_xy(ji,jj)+xzs_xy(ji,jj+1)) ) &
277  / (xxhat(ji+1)-xxhat(ji))
278  zdzsdy=( xzs_xy(ji,jj+1) - xzs_xy(ji,jj) ) &
279  / (xyhat(jj+1)-xyhat(jj))
280  CASE (2)
281  zdzsdx=( xzs_xy(ji+1,jj+1) -xzs_xy(ji,jj+1)) &
282  / (xxhat(ji+1)-xxhat(ji))
283  zdzsdy=( (xzs_xy(ji+1,jj+1)+xzs_xy(ji,jj+1)) &
284  - 2.* xzsl(ji,jj) ) &
285  / (xyhat(jj+1)-xyhat(jj))
286  CASE (3)
287  zdzsdx=( (xzs_xy(ji+1,jj)+xzs_xy(ji+1,jj+1)) &
288  - 2.* xzsl(ji,jj) ) &
289  / (xxhat(ji+1)-xxhat(ji))
290  zdzsdy=( xzs_xy(ji+1,jj+1) - xzs_xy(ji+1,jj) ) &
291  / (xyhat(jj+1)-xyhat(jj))
292  CASE (4)
293  zdzsdx=( xzs_xy(ji+1,jj) - xzs_xy(ji,jj) ) &
294  / (xxhat(ji+1)-xxhat(ji))
295  zdzsdy=( 2.* xzsl(ji,jj) &
296  - (xzs_xy(ji+1,jj)+xzs_xy(ji,jj)) ) &
297  / (xyhat(jj+1)-xyhat(jj))
298  END SELECT
299 !
300  ! If slope is higher than 60 degrees : numerical problems
301  zdzsdx=min(2.0,max(-2.0,zdzsdx))
302  zdzsdy=min(2.0,max(-2.0,zdzsdy))
303 !* slope angles
304 !
305  xslopang(ji,jj,jt) = atan(sqrt(zdzsdx**2+zdzsdy**2))
306  xslopazi(ji,jj,jt) = 1.5*xpi - atan2( zdzsdy, zdzsdx + sign(1.e-30,zdzsdx) )
307 !
308 
309 ! surface of each triangle
310  xsurf_triangle(ji,jj,jt)=sqrt(1. + zdzsdx**2 + zdzsdy**2)
311 
312 !
313 !* normalizes received radiation by the surface of the triangle to obtain
314 ! radiation representative of an horizontal surface.
315 !
316 ! XSSO_SURF(JI,JJ) = XSSO_SURF(JI,JJ) + 0.25*XSURF_TRIANGLE(JI,JJ,JT)
317 !
318  END DO
319  END DO
320 END DO
321 
322 ! 2d arrays for processor domain
323 
324 !------------------------------------------------------------------------------------------
325 
326 
327 END SUBROUTINE init_slope_param
subroutine get_mesh_dim(HGRID, KGRID_PAR, KL, PGRID_PAR, PDX, PDY, PMESHSIZE)
Definition: get_mesh_dim.F90:6
subroutine init_slope_param(UG, PZS, KI, PLAT)