SURFEX v8.1
General documentation of Surfex
regular_grid_spawn.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 ! ################################################################
6  SUBROUTINE regular_grid_spawn(U,KLUOUT, &
7  KL1, KIMAX1,KJMAX1,PX1,PY1,PDX1,PDY1, &
8  KXOR, KYOR, KDXRATIO, KDYRATIO, &
9  KXSIZE, KYSIZE, &
10  KL2, KIMAX_C_ll,KJMAX_C_ll,PX2,PY2,PDX2,PDY2 )
11 ! ################################################################
12 !
13 !!**** *REGULAR_GRID_SPAWN* - routine to read in namelist the horizontal grid
14 !!
15 !! PURPOSE
16 !! -------
17 !!
18 !!** METHOD
19 !! ------
20 !!
21 !! EXTERNAL
22 !! --------
23 !!
24 !!
25 !! IMPLICIT ARGUMENTS
26 !! ------------------
27 !!
28 !! REFERENCE
29 !! ---------
30 !!
31 !!
32 !! AUTHOR
33 !! ------
34 !! V. Masson *Meteo France*
35 !!
36 !! MODIFICATIONS
37 !! -------------
38 !! Original 01/2004
39 !! M.Moge 04/2015 Parallelization using routines from MNH/SURCOUCHE
40 !! M.Moge 06/2015 bug fix for reproductibility using UPDATE_NHALO1D
41 !! M.Moge 01/2016 bug fix for parallel execution with SPLIT2
42 !-------------------------------------------------------------------------------
43 !
44 !* 0. DECLARATIONS
45 ! ------------
46 !
47 USE modd_surf_par, ONLY : nundef
48 !
49 !
50 USE yomhook ,ONLY : lhook, dr_hook
51 USE parkind1 ,ONLY : jprb
52 USE modd_surf_atm_n, ONLY : surf_atm_t
53 !
54 USE modi_abor1_sfx
55 #ifdef MNH_PARALLEL
56 USE mode_ll
57 USE mode_modeln_handler
58 
59 USE mode_splitting_ll, ONLY : split2, def_splitting2
60 USE modd_var_ll, ONLY : nproc, ip, ysplitting
61 USE modd_structure_ll, ONLY : zone_ll, crspd_ll
62 USE modd_parameters, ONLY : jphext
63 USE mode_tools_ll, ONLY : intersection
64 USE mode_exchange_ll, ONLY : send_recv_field
65 USE modi_update_nhalo1d
66 #endif
67 !
68 IMPLICIT NONE
69 !
70 !* 0.1 Declarations of arguments
71 ! -------------------------
72 !
73 TYPE(surf_atm_t), INTENT(INOUT) :: U
74 INTEGER, INTENT(IN) :: KLUOUT ! output listing logical unit
75 INTEGER, INTENT(IN) :: KL1 ! total number of points KIMAX1 * KJMAX1
76 INTEGER, INTENT(IN) :: KIMAX1 ! number of points in x direction
77 INTEGER, INTENT(IN) :: KJMAX1 ! number of points in y direction
78 REAL, DIMENSION(KL1), INTENT(IN) :: PX1 ! X coordinate of all points
79 REAL, DIMENSION(KL1), INTENT(IN) :: PY1 ! Y coordinate of all points
80 REAL, DIMENSION(KL1), INTENT(IN) :: PDX1 ! X mesh size of all points
81 REAL, DIMENSION(KL1), INTENT(IN) :: PDY1 ! Y mesh size of all points
82 INTEGER, INTENT(IN) :: KXOR ! position of modified bottom left point
83 INTEGER, INTENT(IN) :: KYOR ! according to initial grid
84 INTEGER, INTENT(IN) :: KXSIZE ! number of grid meshes in initial grid to be
85 INTEGER, INTENT(IN) :: KYSIZE ! covered by the modified grid
86 INTEGER, INTENT(IN) :: KDXRATIO ! resolution ratio between modified grid
87 INTEGER, INTENT(IN) :: KDYRATIO ! and initial grid
88 INTEGER, INTENT(IN) :: KL2 ! total number of points KIMAX_C_ll * KJMAX_C_ll
89 INTEGER, INTENT(INOUT) :: KIMAX_C_ll ! number of points in x direction (glb on entry, lcl on exit)
90 INTEGER, INTENT(INOUT) :: KJMAX_C_ll ! number of points in y direction (glb on entry, lcl on exit)
91 REAL, DIMENSION(:),ALLOCATABLE, INTENT(OUT) :: PX2 ! X coordinate of all points
92 REAL, DIMENSION(:),ALLOCATABLE, INTENT(OUT) :: PY2 ! Y coordinate of all points
93 REAL, DIMENSION(:),ALLOCATABLE, INTENT(OUT) :: PDX2 ! X mesh size of all points
94 REAL, DIMENSION(:),ALLOCATABLE, INTENT(OUT) :: PDY2 ! Y mesh size of all points
95 !
96 !* 0.2 Declarations of local variables
97 ! -------------------------------
98 !
99 !* coarse/father grid
100 !
101 REAL, DIMENSION(:), ALLOCATABLE :: ZXM1 ! X coordinate of center of mesh (IIMAX1 points)
102 REAL, DIMENSION(:), ALLOCATABLE :: ZYM1 ! Y coordinate of center of mesh (IJMAX1 points)
103 REAL, DIMENSION(:), ALLOCATABLE :: ZXHAT1 ! X coordinate of left side (IIMAX1+1 points)
104 REAL, DIMENSION(:), ALLOCATABLE :: ZYHAT1 ! Y coordinate of bottom side (IJMAX1+1 points)
105 REAL, DIMENSION(:,:,:), ALLOCATABLE :: ZXHAT1_3D, ZYHAT1_3D ! ZXHAT1 and ZXHAT1 copied in a 3D field for the communications
106 !
107 !* fine/son grid
108 !
109 REAL, DIMENSION(:), ALLOCATABLE :: ZXHAT2 ! X coordinate of left side (IIMAX2 points)
110 REAL, DIMENSION(:), ALLOCATABLE :: ZYHAT2 ! Y coordinate of bottom side (IJMAX2 points)
111 REAL, DIMENSION(:), ALLOCATABLE :: ZXHAT2_F_TMP
112 REAL, DIMENSION(:), ALLOCATABLE :: ZYHAT2_F_TMP
113 REAL, DIMENSION(:,:,:), ALLOCATABLE :: ZXHAT2_F, ZYHAT2_F ! temporary 3D fields to communicate the values on the father grid to the local son subgrid
114 !
115 !* other variables
116 !
117 INTEGER :: JL ! loop counter
118 INTEGER :: JI,JJ ! loop controls relatively to modified grid
119 #ifndef MNH_PARALLEL
120 INTEGER :: JIBOX,JJBOX ! grid mesh relatively to initial grid
121 REAL :: ZCOEF ! ponderation coefficient for linear interpolation
122 #endif
123 REAL(KIND=JPRB) :: ZHOOK_HANDLE
124 INTEGER :: IMI
125 INTEGER :: IINFO_ll
126 INTEGER :: IXDOMAINS, IYDOMAINS ! number of subdomains in X and Y directions
127 LOGICAL :: GPREM ! needed for DEF_SPLITTING2, true if NPROC is a prime number
128 INTEGER :: IXOR_F_ll, IYOR_F_ll ! origin of local father subdomain in global coordinates
129 INTEGER :: IXDIM_C, IYDIM_C ! size of local son subdomain (in coarse/father grid)
130 INTEGER :: IXOR_C_ll, IYOR_C_ll ! origin of local son subdomain (in global fine/son grid)
131 INTEGER :: IXEND_C_ll, IYEND_C_ll ! end of local son subdomain (in global fine/son grid)
132 INTEGER :: IXOR_C_COARSE_ll, IYOR_C_COARSE_ll ! origin of local son subdomain (in global coarse/father grid)
133 INTEGER :: IIMAX_C ! number of points in x direction in local portion of son model (in fine grid)
134 INTEGER :: IJMAX_C ! number of points in y direction in local portion of son model (in fine grid)
135 REAL, DIMENSION(KDXRATIO) :: ZCOEFX ! ponderation coefficients for linear interpolation
136 REAL, DIMENSION(KDYRATIO) :: ZCOEFY ! ponderation coefficients for linear interpolation
137 !
138 ! structures for the partitionning
139 !
140 #ifdef MNH_PARALLEL
141 TYPE(zone_ll), DIMENSION(NPROC) :: TZSPLITTING_C !splitting of child model
142 TYPE(zone_ll), ALLOCATABLE, DIMENSION(:) :: TZCOARSEFATHER ! Coarse father grid splitting
143 TYPE(zone_ll), ALLOCATABLE, DIMENSION(:) :: TZCOARSESONSPLIT ! coarse son grid intersection with local father subdomain : coordinates in the father grid
144 !
145 ! structures for the communications
146 !
147 TYPE(zone_ll), ALLOCATABLE, DIMENSION(:) :: TZSEND, TZRECV
148 TYPE(crspd_ll), POINTER :: TZCRSPDSEND, TZCRSPDRECV
149 TYPE(crspd_ll), ALLOCATABLE, DIMENSION(:), TARGET :: TZCRSPDSENDTAB, TZCRSPDRECVTAB
150 #endif
151 !
152 INTEGER :: J
153 INTEGER :: INBMSG
154 INTEGER :: ICARD
155 INTEGER :: ICARDDIF
156 !
157 !------------------------------------------------------------------------------
158 !
159 !* 1. Coherence tests
160 ! ---------------
161 !
162 !* tests
163 !
164 IF (lhook) CALL dr_hook('REGULAR_GRID_SPAWN',0,zhook_handle)
165 #ifdef MNH_PARALLEL
166 IF ( kxor+kxsize-1 > u%NIMAX_SURF_ll ) THEN
167  WRITE(kluout,*) 'spawned domain is not contained in the input domain'
168  WRITE(kluout,*) 'IXOR = ', kxor, ' IXSIZE = ', kxsize,&
169  ' with NIMAX(file) = ', u%NIMAX_SURF_ll
170  CALL abor1_sfx('REGULAR_GRID_SPAWN: (1) SPAWNED DOMAIN NOT CONTAINED IN INPUT DOMAIN')
171 END IF
172 IF ( kyor+kysize-1 > u%NJMAX_SURF_ll ) THEN
173  WRITE(kluout,*) 'spawned domain is not contained in the input domain'
174  WRITE(kluout,*) 'IYOR = ', kyor, ' IYSIZE = ', kysize,&
175  ' with NJMAX(file) = ', u%NJMAX_SURF_ll
176  CALL abor1_sfx('REGULAR_GRID_SPAWN: (2) SPAWNED DOMAIN NOT CONTAINED IN INPUT DOMAIN')
177 END IF
178 #else
179 IF ( kxor+kxsize-1 > kimax1 ) THEN
180  WRITE(kluout,*) 'spawned domain is not contained in the input domain'
181  WRITE(kluout,*) 'IXOR = ', kxor, ' IXSIZE = ', kxsize,&
182  ' with NIMAX(file) = ', kimax1
183  CALL abor1_sfx('REGULAR_GRID_SPAWN: (1) SPAWNED DOMAIN NOT CONTAINED IN INPUT DOMAIN')
184 END IF
185 IF ( kyor+kysize-1 > kjmax1 ) THEN
186  WRITE(kluout,*) 'spawned domain is not contained in the input domain'
187  WRITE(kluout,*) 'IYOR = ', kyor, ' IYSIZE = ', kysize,&
188  ' with NJMAX(file) = ', kjmax1
189  CALL abor1_sfx('REGULAR_GRID_SPAWN: (2) SPAWNED DOMAIN NOT CONTAINED IN INPUT DOMAIN')
190 END IF
191 #endif
192 
193 !
194 !------------------------------------------------------------------------------
195 !
196 !* 2. Partitionning of the son subdomain
197 ! --------------------------------------------------------------
198 !
199 #ifdef MNH_PARALLEL
200 ! get origin of local father subdomain in global coordinates
201 !
202  CALL get_or_ll( "B", ixor_f_ll, iyor_f_ll )
203 !
204 ! origin of local son subdomain in global father coordinates
205 !
206 !IXOR_C_COARSE_ll = MAX( IXOR_F_ll, KXOR+1 )
207 !IYOR_C_COARSE_ll = MAX( IYOR_F_ll, KYOR+1 )
208 ixor_c_coarse_ll = max( ixor_f_ll-1, kxor ) ! we have to add one point on the west and south sides -> hence the "- 1"
209 iyor_c_coarse_ll = max( iyor_f_ll-1, kyor ) ! we have to add one point on the west and south sides -> hence the "- 1"
210 !
211 ALLOCATE(tzcoarsefather(nproc))
212 ALLOCATE(tzcoarsesonsplit(nproc))
213 !
214 ! compute father partitioning
215 !
216  CALL split2( u%NIMAX_SURF_ll, u%NJMAX_SURF_ll, 1, nproc,tzcoarsefather, ysplitting)
217 ! we don't want the halo
218 DO j = 1, nproc
219  tzcoarsefather(j)%NXOR = tzcoarsefather(j)%NXOR - jphext
220  tzcoarsefather(j)%NYOR = tzcoarsefather(j)%NYOR - jphext
221  tzcoarsefather(j)%NXEND = tzcoarsefather(j)%NXEND - jphext
222  tzcoarsefather(j)%NYEND = tzcoarsefather(j)%NYEND - jphext
223 ENDDO
224 !
225 ! partition son domain on father grid (with global coordinates on father grid)
226 !
227 ! we have to add one point on the west and south sides -> hence the "- 1"
228 ! Warning : we cannot just call SPLIT2(KXSIZE, KYSIZE, 1, NPROC, TZCOARSESONSPLIT, YSPLITTING) as it would not
229 ! necessarily split the son domain the same way the father domain was splitted
230 ! example : if father domain is 30x40 and son domain is 6x5 (in father grid dimensions) then
231 ! with NPROC = 2, SPLIT2 will split father domain along Y dimension -> 30x20 local domains
232 ! but SPLIT2 will split son domain along X dimension -> 3x5 local domains.
233 ! therefore we have to use DEF_SPLITTING2 and force the decomposition in the call to SPLIT2
234 ! we want the same domain partitioning for the child domain and for the father domain
235  CALL def_splitting2(ixdomains,iydomains, u%NIMAX_SURF_ll, u%NJMAX_SURF_ll,nproc,gprem)
236  CALL split2(kxsize, kysize, 1, nproc, tzcoarsesonsplit, ysplitting, ixdomains, iydomains)
237 
238 ! compute the local size of son grid
239 ! KIMAX_C_ll, KJMAX_C_ll are the global sizes of son domain
240 iimax_c = ( tzcoarsesonsplit(ip)%NXEND - tzcoarsesonsplit(ip)%NXOR + 1 ) * kdxratio
241 ijmax_c = ( tzcoarsesonsplit(ip)%NYEND - tzcoarsesonsplit(ip)%NYOR + 1 ) * kdyratio
242 ! get the coordinates of the son domain partition on father grid
243 DO j = 1, nproc
244  tzcoarsesonsplit(j)%NXOR = tzcoarsesonsplit(j)%NXOR + kxor - jphext - 1
245  tzcoarsesonsplit(j)%NYOR = tzcoarsesonsplit(j)%NYOR + kyor - jphext - 1
246  tzcoarsesonsplit(j)%NXEND = tzcoarsesonsplit(j)%NXEND + kxor - jphext
247  tzcoarsesonsplit(j)%NYEND = tzcoarsesonsplit(j)%NYEND + kyor - jphext
248 ENDDO
249 !
250 ! compute the local size of son grid
251 ! KIMAX_C_ll, KJMAX_C_ll are the global sizes of son domain
252 !
253 !CALL SPLIT2 ( KIMAX_C_ll, KJMAX_C_ll, 1, NPROC, TZSPLITTING_C, YSPLITTING )
254 !IXOR_C_ll = TZSPLITTING_C(IP)%NXOR - JPHEXT
255 !IXEND_C_ll = TZSPLITTING_C(IP)%NXEND - JPHEXT
256 !IYOR_C_ll = TZSPLITTING_C(IP)%NYOR - JPHEXT
257 !IYEND_C_ll = TZSPLITTING_C(IP)%NYEND - JPHEXT
258 !!
259 !IIMAX_C = IXEND_C_ll - IXOR_C_ll + 1
260 !IJMAX_C = IYEND_C_ll - IYOR_C_ll + 1
261 !IIMAX_C = ( TZCOARSESONSPLIT(IP)%NXEND - TZCOARSESONSPLIT(IP)%NXOR + 1 ) * KDXRATIO
262 !IJMAX_C = ( TZCOARSESONSPLIT(IP)%NYEND - TZCOARSESONSPLIT(IP)%NYOR + 1 ) * KDYRATIO
263 !
264 !------------------------------------------------------------------------------
265 !
266 !* 3. Preparing the structures for the communications for the initialization of son fields using father fields
267 ! --------------------------------------------------------------
268 !
269  !
270  ! ######## initializing the structures for the SEND ########
271  !
272  ALLOCATE(tzsend(nproc))
273  CALL intersection( tzcoarsesonsplit, nproc, tzcoarsefather(ip), tzsend)
274  ! il faut initialiser le TAG de manière a avoir un meme tag unique pour le send et le recv :
275  ! on concatene le num du proc qui envoie et le num du proc qui recoit
276  DO j = 1, nproc
277  IF ( tzsend(j)%NUMBER > 0 ) THEN
278  IF (tzsend(j)%NUMBER == 1) THEN
279  tzsend(j)%MSSGTAG = ip * 10 + 1
280  ELSE
281  tzsend(j)%MSSGTAG = ip * 10**(ceiling(log10(real(tzsend(j)%number)))) + tzsend(j)%number
282  ENDIF
283  ENDIF
284  ENDDO
285  ! switching to local coordinates
286  DO j = 1, nproc
287  IF ( tzsend(j)%NUMBER > 0 ) THEN
288  tzsend(j)%NXOR = tzsend(j)%NXOR - ixor_f_ll + 1
289  tzsend(j)%NXEND = tzsend(j)%NXEND - ixor_f_ll + 1
290  tzsend(j)%NYOR = tzsend(j)%NYOR - iyor_f_ll + 1
291  tzsend(j)%NYEND = tzsend(j)%NYEND - iyor_f_ll + 1
292  ENDIF
293  ENDDO
294  ! we do not need the Z dimension
295  DO j = 1, nproc
296  IF ( tzsend(j)%NUMBER > 0 ) THEN
297  tzsend(j)%NZOR = 1
298  tzsend(j)%NZEND = 1
299  ENDIF
300  ENDDO
301  ! switching from an array of CRSPD_ll to a CRSPD_ll pointer
302  inbmsg = 0
303  DO j = 1, nproc
304  IF ( tzsend(j)%NUMBER > 0 ) THEN
305  inbmsg = inbmsg+1
306  ENDIF
307  ENDDO
308  IF ( inbmsg > 0 ) THEN
309  ALLOCATE( tzcrspdsendtab(inbmsg) )
310  icard = 0
311  icarddif = 0
312  DO j = 1, nproc
313  IF ( tzsend(j)%NUMBER > 0 ) THEN
314  icard = icard+1
315  IF ( tzsend(icard)%NUMBER /= ip ) THEN
316  icarddif = icarddif+1
317  ENDIF
318  tzcrspdsendtab(icard)%TELT = tzsend(j)
319  IF ( icard == inbmsg ) THEN
320  tzcrspdsendtab(icard)%TNEXT => null()
321  ELSE
322  tzcrspdsendtab(icard)%TNEXT => tzcrspdsendtab(icard+1)
323  ENDIF
324  ENDIF
325  ENDDO
326  DO j = 1, icard
327  tzcrspdsendtab(j)%NCARD = icard
328  tzcrspdsendtab(j)%NCARDDIF = icarddif
329  ENDDO
330  ELSE
331  !il faut tout de meme mettre un element de taille 0 dans TZCRSPDSENDTAB
332  !sinon SEND_RECV_FIELD plante en 02
333  ALLOCATE( tzcrspdsendtab(1) )
334  icard = 0
335  icarddif = 0
336  tzcrspdsendtab(1)%TELT = tzsend(1)
337  tzcrspdsendtab(1)%TNEXT => null()
338  tzcrspdsendtab(1)%NCARD = 0
339  tzcrspdsendtab(1)%NCARDDIF = 0
340  ENDIF
341  IF (icard > 0) THEN
342  tzcrspdsend => tzcrspdsendtab(1)
343  ELSE
344  tzcrspdsend => null()
345  ENDIF
346  !
347  ! ######## initializing the structures for the RECV ########
348  !
349  ALLOCATE(tzrecv(nproc))
350  CALL intersection( tzcoarsefather, nproc, tzcoarsesonsplit(ip), tzrecv )
351  ! il faut initialiser le TAG de manière a avoir un meme tag unique pour le send et le recv :
352  ! on concatene le num du proc qui envoie et le num du proc qui recoit
353  DO j = 1, nproc
354  IF ( tzrecv(j)%NUMBER > 0 ) THEN
355  IF (ip == 1) THEN
356  tzrecv(j)%MSSGTAG = tzrecv(j)%NUMBER * 10 + 1
357  ELSE
358  tzrecv(j)%MSSGTAG = tzrecv(j)%NUMBER * 10**(ceiling(log10(real(ip)))) + ip
359  ENDIF
360  ENDIF
361  ENDDO
362  ! switching to local coordinates
363  DO j = 1, nproc
364  IF ( tzrecv(j)%NUMBER > 0 ) THEN
365  tzrecv(j)%NXOR = tzrecv(j)%NXOR - tzcoarsesonsplit(ip)%NXOR + 1
366  tzrecv(j)%NXEND = tzrecv(j)%NXEND - tzcoarsesonsplit(ip)%NXOR + 1
367  tzrecv(j)%NYOR = tzrecv(j)%NYOR - tzcoarsesonsplit(ip)%NYOR + 1
368  tzrecv(j)%NYEND = tzrecv(j)%NYEND - tzcoarsesonsplit(ip)%NYOR + 1
369  ENDIF
370  ENDDO
371  ! we do not need the Z dimension
372  DO j = 1, nproc
373  IF ( tzrecv(j)%NUMBER > 0 ) THEN
374  tzrecv(j)%NZOR = 1
375  tzrecv(j)%NZEND = 1
376  ENDIF
377  ENDDO
378  ! switching from an array of CRSPD_ll to a CRSPD_ll pointer
379  inbmsg = 0
380  DO j = 1, nproc
381  IF ( tzrecv(j)%NUMBER > 0 ) THEN
382  inbmsg = inbmsg+1
383  ENDIF
384  ENDDO
385  IF ( inbmsg > 0 ) THEN
386  ALLOCATE( tzcrspdrecvtab(inbmsg) )
387  icard = 0
388  icarddif = 0
389  DO j = 1, nproc
390  IF ( tzrecv(j)%NUMBER > 0 ) THEN
391  icard = icard+1
392  IF ( tzrecv(icard)%NUMBER /= ip ) THEN
393  icarddif = icarddif+1
394  ENDIF
395  tzcrspdrecvtab(icard)%TELT = tzrecv(j)
396  IF ( icard == inbmsg ) THEN
397  tzcrspdrecvtab(icard)%TNEXT => null()
398  ELSE
399  tzcrspdrecvtab(icard)%TNEXT => tzcrspdrecvtab(icard+1)
400  ENDIF
401  ENDIF
402  ENDDO
403  DO j = 1, icard
404  tzcrspdrecvtab(j)%NCARD = icard
405  tzcrspdrecvtab(j)%NCARDDIF = icarddif
406  ENDDO
407  ELSE
408  !il faut tout de meme mettre un element de taille 0 dans TZCRSPDRECVTAB
409  !sinon SEND_RECV_FIELD plante en 02
410  ALLOCATE( tzcrspdrecvtab(1) )
411  icard = 0
412  icarddif = 0
413  tzcrspdrecvtab(1)%TELT = tzsend(1)
414  tzcrspdrecvtab(1)%TNEXT => null()
415  tzcrspdrecvtab(1)%NCARD = 0
416  tzcrspdrecvtab(1)%NCARDDIF = 0
417  ENDIF
418  IF (icard > 0) THEN
419  tzcrspdrecv => tzcrspdrecvtab(1)
420  ELSE
421  tzcrspdrecv => null()
422  ENDIF
423 #else
424 iimax_c = kimax_c_ll
425 ijmax_c = kjmax_c_ll
426 #endif
427 !
428 !------------------------------------------------------------------------------
429 !
430 !* 4. Center of mesh coordinate arrays for each direction separately
431 ! --------------------------------------------------------------
432 !
433 ! allocate the fields on the local son grid
434 !
435 #ifdef MNH_PARALLEL
436 ALLOCATE(px2(iimax_c*ijmax_c))
437 ALLOCATE(py2(iimax_c*ijmax_c))
438 ALLOCATE(pdx2(iimax_c*ijmax_c))
439 ALLOCATE(pdy2(iimax_c*ijmax_c))
440 #else
441 ALLOCATE(px2(kl2))
442 ALLOCATE(py2(kl2))
443 ALLOCATE(pdx2(kl2))
444 ALLOCATE(pdy2(kl2))
445 #endif
446 !
447 ALLOCATE(zxhat2(iimax_c+1))
448 ALLOCATE(zyhat2(ijmax_c+1))
449 !
450 ! allocate the fields on the local father grid
451 !
452 ALLOCATE(zxm1(kimax1))
453 ALLOCATE(zym1(kjmax1))
454 ALLOCATE(zxhat1(kimax1+1))
455 ALLOCATE(zyhat1(kjmax1+1))
456 !
457 zxm1(:) = px1(1:kimax1)
458 DO jl=1,kl1
459  IF (mod(jl,kimax1)==0) zym1(jl/kimax1) = py1(jl)
460 END DO
461 !
462 !------------------------------------------------------------------------------
463 !
464 !* 5. side of mesh coordinate arrays for each direction separately
465 ! ------------------------------------------------------------
466 !
467 !
468 IF (kimax1==1) THEN
469  zxhat1(1) = zxm1(1) - 0.5 * pdx1(1)
470  zxhat1(2) = zxm1(1) + 0.5 * pdx1(1)
471 ELSE
472  zxhat1(1) = 1.5 * zxm1(1) - 0.5 * zxm1(2)
473  DO ji=2,kimax1
474  zxhat1(ji) = 0.5 * zxm1(ji-1) + 0.5 * zxm1(ji)
475  END DO
476  zxhat1(kimax1+1) = 1.5 * zxm1(kimax1) - 0.5 * zxm1(kimax1-1)
477 END IF
478 !
479 IF (kjmax1==1) THEN
480  zyhat1(1) = zym1(1) - 0.5 * pdy1(1)
481  zyhat1(2) = zym1(1) + 0.5 * pdy1(1)
482 ELSE
483  zyhat1(1) = 1.5 * zym1(1) - 0.5 * zym1(2)
484  DO jj=2,kjmax1
485  zyhat1(jj) = 0.5 * zym1(jj-1) + 0.5 * zym1(jj)
486  END DO
487  zyhat1(kjmax1+1) = 1.5 * zym1(kjmax1) - 0.5 * zym1(kjmax1-1)
488 END IF
489 #ifdef MNH_PARALLEL
490  !
491  ! do the communication
492  !
493  ixdim_c = tzcoarsesonsplit(ip)%NXEND-tzcoarsesonsplit(ip)%NXOR+1
494  iydim_c = tzcoarsesonsplit(ip)%NYEND-tzcoarsesonsplit(ip)%NYOR+1
495  ALLOCATE(zxhat2_f(ixdim_c,iydim_c,1))
496  ALLOCATE(zyhat2_f(ixdim_c,iydim_c,1))
497  ALLOCATE(zxhat1_3d(kimax1,kjmax1,1))
498  ALLOCATE(zyhat1_3d(kimax1,kjmax1,1))
499  zxhat1_3d(:,:,:) = 0
500  zyhat1_3d(:,:,:) = 0
501  zxhat2_f(:,:,:) = 0
502  zyhat2_f(:,:,:) = 0
503  DO j=1, kjmax1
504  zxhat1_3d(:,j,1) = zxhat1(1:kimax1)
505  ENDDO
506  DO j=1, kimax1
507  zyhat1_3d(j,:,1) = zyhat1(1:kjmax1)
508  ENDDO
509  CALL send_recv_field( tzcrspdsend, tzcrspdrecv, zxhat1_3d, zxhat2_f, iinfo_ll)
510  CALL send_recv_field( tzcrspdsend, tzcrspdrecv, zyhat1_3d, zyhat2_f, iinfo_ll)
511 !
512 ! We have to copy the entries of ZXHAT1_3D and ZYHAT1_3D that are local to the current process,
513 ! and that are therefore not communicated in SEND_RECV_FIELD, in ZXHAT2_F and ZYHAT2_F
514 !
515  IF ( tzsend(ip)%NUMBER /= 0 ) THEN !if there are entries of ZXHAT1_3D and ZYHAT1_3D that are local to the current process
516 ! DO J=TZSEND(IP)%NXOR-KXOR,TZSEND(IP)%NXEND-KXOR
517  zxhat2_f( tzrecv(ip)%NXOR:tzrecv(ip)%NXEND, 1, 1) = zxhat1_3d( tzsend(ip)%NXOR:tzsend(ip)%NXEND, 1, 1)
518 ! ENDDO
519 ! DO J=TZSEND(IP)%NYOR-KYOR,TZSEND(IP)%NYEND-KYOR
520  zyhat2_f( 1,tzrecv(ip)%NYOR:tzrecv(ip)%NYEND, 1) = zyhat1_3d( 1,tzsend(ip)%NYOR:tzsend(ip)%NYEND, 1)
521 ! ENDDO
522  ENDIF
523  !
524  ! We need one halo point on the east and north sides of each local subdomain to do a proper interpolation
525  !
526  ALLOCATE( zxhat2_f_tmp(ixdim_c+1) )
527  ALLOCATE( zyhat2_f_tmp(iydim_c+1) )
528  zxhat2_f_tmp(:) = 0.
529  zyhat2_f_tmp(:) = 0.
530  zxhat2_f_tmp(1:ixdim_c) = zxhat2_f(:,1,1)
531  zyhat2_f_tmp(1:iydim_c) = zyhat2_f(1,:,1)
532 ! we want the same domain partitioning for the child domain and for the father domain
533  CALL def_splitting2(ixdomains,iydomains, u%NIMAX_SURF_ll, u%NJMAX_SURF_ll,nproc,gprem)
534  CALL split2(kxsize, kysize, 1, nproc, tzcoarsesonsplit, ysplitting, ixdomains, iydomains)
535  CALL update_nhalo1d( 1, zxhat2_f_tmp, kxsize, kysize,tzcoarsesonsplit(ip)%NXOR, &
536  tzcoarsesonsplit(ip)%NXEND,tzcoarsesonsplit(ip)%NYOR,tzcoarsesonsplit(ip)%NYEND, 'XX ')
537  CALL update_nhalo1d( 1, zyhat2_f_tmp, kxsize, kysize,tzcoarsesonsplit(ip)%NXOR, &
538  tzcoarsesonsplit(ip)%NXEND,tzcoarsesonsplit(ip)%NYOR,tzcoarsesonsplit(ip)%NYEND, 'YY ')
539 #endif
540 !
541 !------------------------------------------------------------------------------
542 !
543 !* 6. Interpolation of coordinate arrays for each direction separately
544 ! ----------------------------------------------------------------
545 !
546 !* X coordinate array
547 !
548 #ifndef MNH_PARALLEL
549 DO ji=1,iimax_c
550  jibox=(ji-1)/kdxratio + kxor
551  zcoef= float(mod(ji-1,kdxratio))/float(kdxratio)
552  zxhat2(ji)=(1.-zcoef)*zxhat1(jibox)+zcoef*zxhat1(jibox+1)
553 END DO
554 IF (iimax_c==1) THEN
555  zxhat2(iimax_c+1) = zxhat2(iimax_c) + zxhat1(jibox+1) - zxhat1(jibox)
556 ELSE
557  zxhat2(iimax_c+1) = 2. * zxhat2(iimax_c) - zxhat2(iimax_c-1)
558 END IF
559 #else
560 DO j=0,kdxratio-1
561  zcoefx(j+1) = float(j)/float(kdxratio)
562 ENDDO
563 DO ji=1,ixdim_c-1
564  DO jj=1,kdxratio
565  zxhat2((ji-1)*kdxratio+jj)=(1.-zcoefx(jj))*zxhat2_f(ji,1,1)+zcoefx(jj)*zxhat2_f(ji+1,1,1)
566  ENDDO
567 ENDDO
568 IF (iimax_c==1) THEN
569  zxhat2(iimax_c+1) = zxhat2(iimax_c) + zxhat2_f(ji,1,1) - zxhat2_f(ji,1,1)
570 ELSE
571  IF ( least_ll() ) THEN ! the east halo point does not have a correct value so have to do an extrapolation
572  zxhat2(iimax_c+1) = 2. * zxhat2(iimax_c) - zxhat2(iimax_c-1)
573  ELSE
574  zxhat2(iimax_c+1)=(1.-zcoefx(1))*zxhat2_f_tmp(ixdim_c)+zcoefx(1)*zxhat2_f_tmp(ixdim_c+1)
575  ENDIF
576 END IF
577 #endif
578 !
579 !* Y coordinate array
580 !
581 #ifndef MNH_PARALLEL
582 DO jj=1,ijmax_c
583  jjbox=(jj-1)/kdyratio + kyor
584  zcoef= float(mod(jj-1,kdyratio))/float(kdyratio)
585  zyhat2(jj)=(1.-zcoef)*zyhat1(jjbox)+zcoef*zyhat1(jjbox+1)
586 END DO
587 IF (ijmax_c==1) THEN
588  zyhat2(ijmax_c+1) = zyhat2(ijmax_c) + zyhat1(jjbox+1) - zyhat1(jjbox)
589 ELSE
590  zyhat2(ijmax_c+1) = 2. * zyhat2(ijmax_c) - zyhat2(ijmax_c-1)
591 END IF
592 #else
593 DO j=0,kdyratio-1
594  zcoefy(j+1) = float(j)/float(kdyratio)
595 ENDDO
596 DO ji=1,iydim_c-1
597  DO jj=1,kdyratio
598  zyhat2((ji-1)*kdyratio+jj)=(1.-zcoefy(jj))*zyhat2_f(1,ji,1)+zcoefy(jj)*zyhat2_f(1,ji+1,1)
599  ENDDO
600 ENDDO
601 IF (ijmax_c==1) THEN
602  zyhat2(ijmax_c+1) = zyhat2(ijmax_c) + zyhat2_f(1,ji,1) - zyhat2_f(1,ji,1)
603 ELSE
604  IF ( lnorth_ll() ) THEN ! the east halo point does not have a correct value so have to do an extrapolation
605  zyhat2(ijmax_c+1) = 2. * zyhat2(ijmax_c) - zyhat2(ijmax_c-1)
606  ELSE
607  zyhat2(ijmax_c+1)=(1.-zcoefy(1))*zyhat2_f_tmp(iydim_c)+zcoefy(1)*zyhat2_f_tmp(iydim_c+1)
608  ENDIF
609 END IF
610 #endif
611 !---------------------------------------------------------------------------
612 DEALLOCATE(zxm1)
613 DEALLOCATE(zym1)
614 DEALLOCATE(zxhat1)
615 DEALLOCATE(zyhat1)
616 #ifdef MNH_PARALLEL
617 DEALLOCATE(zxhat1_3d)
618 DEALLOCATE(zyhat1_3d)
619 #endif
620 !------------------------------------------------------------------------------
621 !
622 !* 7. Coordinate arrays of all points
623 ! -------------------------------
624 !
625 DO jj=1,ijmax_c
626  DO ji=1,iimax_c
627  jl = (jj-1) * iimax_c + ji
628  px2(jl) = 0.5 * zxhat2(ji) + 0.5 * zxhat2(ji+1)
629  pdx2(jl) = zxhat2(ji+1) - zxhat2(ji)
630  py2(jl) = 0.5 * zyhat2(jj) + 0.5 * zyhat2(jj+1)
631  pdy2(jl) = zyhat2(jj+1) - zyhat2(jj)
632  END DO
633 END DO
634 !
635 #ifdef MNH_PARALLEL
636 kimax_c_ll = iimax_c
637 kjmax_c_ll = ijmax_c
638 #endif
639 !---------------------------------------------------------------------------
640 #ifdef MNH_PARALLEL
641 DEALLOCATE(zxhat2_f)
642 DEALLOCATE(zyhat2_f)
643 DEALLOCATE(tzcrspdsendtab)
644 DEALLOCATE(tzcrspdrecvtab)
645 DEALLOCATE(tzsend)
646 DEALLOCATE(tzrecv)
647 DEALLOCATE(tzcoarsefather)
648 DEALLOCATE(tzcoarsesonsplit)
649 #endif
650 DEALLOCATE(zxhat2)
651 DEALLOCATE(zyhat2)
652 IF (lhook) CALL dr_hook('REGULAR_GRID_SPAWN',1,zhook_handle)
653 !---------------------------------------------------------------------------
654 !
655 END SUBROUTINE regular_grid_spawn
static int nproc
Definition: drhook.c:436
subroutine regular_grid_spawn(U, KLUOUT,
subroutine abor1_sfx(YTEXT)
Definition: abor1_sfx.F90:7
integer, parameter jprb
Definition: parkind1.F90:32
integer, parameter nundef
logical lhook
Definition: yomhook.F90:15
int number
Definition: privpub.h:314