SURFEX v8.1
General documentation of Surfex
sfx_xios_send_block.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 sfx_xios_send_block(HDTAG,PFIELD,PFIELD2,PFIELD3,&
6  HDOMAIN,HAXIS,HAXIS2,HDCOMMENT,KFREQOP)
7 !!
8 !!
9 !! PURPOSE
10 !! --------
11 !!
12 !! Front-end to XIOS for client models
13 !!
14 !! It performes field declaration to XIOS if needed, provided it is
15 !! not too late with respect to xios context definition closing
16 !! (see sfx_xios_declare_field)
17 !!
18 !! It copes with client models which process fields by 'blocks'
19 !! over the first dimension, and wish to send them by blocks too,
20 !! a set of blocks being provided, duly ordered, between two
21 !! calendar updates
22 !!
23 !! It gathers field blocks and send them to XIOS, using
24 !! xios_send_field, as soon as the field is complete (i.e. enough
25 !! blocks have been received, compared to a MODD_XIOS variable)
26 !!
27 !! METHOD :
28 !! --------------------
29 !!
30 !! For each new field name received, create an entry in buffer
31 !! array and records full MPI-task field size (as known by
32 !! Xios).
33 !!
34 !! For all field names, add the block to the buffer and, if field
35 !! is complete, send it to Xios and clears the buffer
36 !!
37 !! EXTERNAL
38 !! --------
39 !!
40 !! XIOS LIBRARY
41 !!
42 !!
43 !! REFERENCE
44 !! ---------
45 !!
46 !! XIOS Reference guide - Yann Meurdesoif - 10/10/2014 -
47 !! svn co --r 515 http://forge.ipsl.jussieu.fr/ioserver/svn/XIOS/branchs/xios-1.0 <dir>
48 !! cd <dir>/doc ; ....
49 !!
50 !! AUTHOR
51 !! ------
52 !!
53 !! S.Sénési, CNRM
54 !!
55 !! MODIFICATION
56 !! --------------
57 !!
58 !! Original 01/2016
59 !!
60 !-------------------------------------------------------------------------------
61 !
62 !* 0. DECLARATIONS
63 ! ------------
64 !
65 USE modd_surfex_mpi, ONLY : nrank
66 !
68 !
69 ! NBLOCK dans arpege : YOMDIM:NGPBLKS
70 #ifdef WXIOS
71 USE modi_sfx_xios_declare_field
72 USE xios ,ONLY : xios_is_defined_field_attr, xios_get_field_attr, &
73  xios_is_defined_grid_attr, xios_get_grid_attr, &
74  xios_is_defined_domain_attr, xios_get_domain_attr, &
75  xios_is_valid_field, xios_send_field, xios_set_field_attr,&
76  xios_get_handle, xios_add_child, xios_set_attr,&
77  xios_field, xios_fieldgroup, xios_field_is_active,&
78  xios_update_calendar
79 #endif
80 !
81 USE modi_abor1_sfx
82 !
83 USE yomhook , ONLY : lhook, dr_hook
84 USE parkind1 , ONLY : jpim, jprb
85 !
86 IMPLICIT NONE
87 !
88 ! Arguments
89 !
90  CHARACTER(LEN=*), INTENT(IN) :: HDTAG ! Field name
91 REAL(KIND=JPRB) , INTENT(IN), OPTIONAL, DIMENSION(:) :: PFIELD ! Field data block
92 REAL(KIND=JPRB) , INTENT(IN), OPTIONAL, DIMENSION(:,:):: PFIELD2 ! (or) 2d field data block
93 REAL(KIND=JPRB) , INTENT(IN), OPTIONAL, DIMENSION(:,:,:):: PFIELD3 ! (or) 3d field data block
94  CHARACTER(LEN=*), INTENT(IN), OPTIONAL :: HDOMAIN ! Field domain name, defaults to 'FULL'
95  CHARACTER(LEN=*), INTENT(IN), OPTIONAL :: HAXIS ! Axis name, for 2d fields
96  CHARACTER(LEN=*), INTENT(IN), OPTIONAL :: HAXIS2 ! 2nd axis name, for 3d fields
97  CHARACTER(LEN=*), INTENT(IN), OPTIONAL :: HDCOMMENT ! Comment 'a la Surfex' (i.e. '<long name> (<units>)')
98  INTEGER , INTENT(IN), OPTIONAL :: KFREQOP ! Sampling frequency, in minutes
99 !
100 ! Local variables
101 !
102 #ifdef WXIOS
103 !
104 ! A basic type for handling fields and their buffer
105 !
106 TYPE buf_t
107  CHARACTER(LEN=100) :: YLNAME ! Field name , as for XIOS
108  INTEGER(KIND=JPIM) :: ISIZEMAX ! Expected size of the complete field
109  ! for the whole of the MPI task
110  INTEGER(KIND=JPIM) :: ISIZE ! Current usable size (ie. over received blocks)
111  INTEGER(KIND=JPIM) :: INDIM ! Number of dimensions
112  INTEGER(KIND=JPIM) :: ILEV ! Size of 2nd dim (from first call)
113  INTEGER(KIND=JPIM) :: ILEV2 ! Size of 3rd dim (from first call)
114  INTEGER(KIND=JPIM) :: IBLOCK ! Number of blocks received for current timestep
115  REAL(KIND=JPRB), ALLOCATABLE, DIMENSION (:,:,:) :: ZFIELD ! Accumulate received blocks
116 END TYPE buf_t
117 !
118 TYPE(xios_field) :: field_hdl, other_field_hdl
119 TYPE(xios_fieldgroup) :: fieldgroup_hdl
120 INTEGER(KIND=JPIM) :: ISIZE = 1000 ! Initial number of managed field entries
121 INTEGER(KIND=JPIM), PARAMETER :: INCR = 100 ! Increment in field entries number when reallocating
122 INTEGER(KIND=JPIM), PARAMETER :: IMAXSIZE = 10000 ! Max number of field entries
123 !
124 TYPE(buf_t), POINTER :: YLF ! Current buffer entry
125 TYPE(buf_t), ALLOCATABLE, TARGET, SAVE :: YLFIELDS(:)! Array of buffer entries
126 TYPE(buf_t), ALLOCATABLE :: YLTEMP(:) ! id - temporary
127 !
128 INTEGER(KIND=JPIM) :: JI, IL, IEMPTY, IIDIM, ITAKE, ILEV, INFIELDS
129  CHARACTER(LEN=100) :: YLTAG ! Field name
130  CHARACTER(LEN=300) :: YLAXIS, YLAXIS2
131  CHARACTER(LEN=300) :: YLDOMAIN
132  CHARACTER(LEN=300) :: YLGRID
133  CHARACTER(LEN=300) :: YLCOMMENT
134 !
135 INTEGER :: IFREQOP
136 !
137 LOGICAL :: GLISDEF
138 !
139 #endif
140 !
141 REAL(KIND=JPRB) :: ZHOOK_HANDLE
142 !
143 !#include "abor1.intfb.h"
144 !
145 IF (lhook) CALL dr_hook('SFX_XIOS_SEND_BLOCK_1',0,zhook_handle)
146 !
147 IF (.NOT. lxios) THEN
148  IF (lhook) CALL dr_hook('SFX_XIOS_SEND_BLOCK_1',1,zhook_handle)
149  RETURN
150 ENDIF
151 !
152 #ifdef WXIOS
153 !
154 IF (lxios_def_closed) THEN
155  IF (.NOT. xios_field_is_active(hdtag) ) THEN
156  IF (lhook) CALL dr_hook('SFX_XIOS_SEND_BLOCK_1',1,zhook_handle)
157  RETURN
158  ENDIF
159 ENDIF
160 yltag = trim(hdtag)
161 !
162 !$OMP SINGLE
163 !
164 ALLOCATE(ylfields(isize))
165 ylfields(:)%YLNAME = ''
166 !
167 ! Search if field is known - a simple loop on the table -
168 ! probably not much quick ...
169 !
170 il = 0
171 DO ji=1,isize
172  IF (ylfields(ji)%YLNAME == yltag) THEN
173  il = ji
174  EXIT
175  ENDIF
176 ENDDO
177 !
178 IF (lhook) CALL dr_hook('SFX_XIOS_SEND_BLOCK_1',1,zhook_handle)
179 !
180 IF ( il==0 ) THEN
181  !
182  ! Field is not yet recorded -> ask XIOS if field is known, and what's its size
183  ! By exception : if XIOS still in init phase, declare field domain if needed
184  !
185  IF (.NOT. lxios_def_closed) THEN
186 
187 IF (lhook) CALL dr_hook('SFX_XIOS_SEND_BLOCK_2',0,zhook_handle)
188 
189  yldomain=''
190  IF (PRESENT(hdomain)) yldomain = trim(hdomain)
191  ylcomment=''
192  IF (PRESENT(hdcomment)) ylcomment = trim(hdcomment)
193  ifreqop=0
194  IF (PRESENT(kfreqop)) ifreqop = kfreqop
195  !
196  IF (PRESENT(pfield)) THEN
197  CALL sfx_xios_declare_field(yltag, yldomain, hcomment=ylcomment, kfreqop=ifreqop)
198  ELSEIF (PRESENT(pfield2)) THEN
199  ylaxis=''
200  IF (PRESENT(haxis)) ylaxis = trim(haxis)
201  CALL sfx_xios_declare_field(yltag, yldomain, haxis=ylaxis, &
202  klev=SIZE(pfield2,2), hcomment=ylcomment,kfreqop=ifreqop)
203  ELSEIF (PRESENT(pfield3)) THEN
204  ylaxis ='' ; IF (PRESENT(haxis)) ylaxis = trim(haxis)
205  ylaxis2='' ; IF (PRESENT(haxis2)) ylaxis2 = trim(haxis2)
206  CALL sfx_xios_declare_field(yltag, yldomain, &
207  haxis =ylaxis , klev =SIZE(pfield3,2), &
208  haxis2=ylaxis2, klev2=SIZE(pfield3,3), hcomment=ylcomment,kfreqop=ifreqop)
209  ELSE
210  CALL abor1_sfx("SFX_XIOS_SEND_BLOCK: NO PFIELDx FOR "//trim(yltag))
211  ENDIF
212  !
213 IF (lhook) CALL dr_hook('SFX_XIOS_SEND_BLOCK_2',1,zhook_handle)
214 
215  ELSE
216  !
217  IF (.NOT. xios_is_valid_field(yltag)) THEN
218  CALL abor1_sfx("SFX_XIOS_SEND_BLOCK: FIELD "//trim(yltag)//&
219  &" WASN'T DECLARED TO XIOS (NEITHER IN XML CONFIG FILE, NOR SOON ENOUGH FROM CODE)")
220  ENDIF
221  !
222  ! Find a place (i.e. index IEMPTY) to record the new field
223  !
224 IF (lhook) CALL dr_hook('SFX_XIOS_SEND_BLOCK_3',0,zhook_handle)
225 
226  iempty = 0
227  DO ji = 1,isize
228  IF (trim(ylfields(ji)%YLNAME) == '') THEN
229  iempty = ji
230  EXIT
231  ENDIF
232  ENDDO
233  !
234 IF (lhook) CALL dr_hook('SFX_XIOS_SEND_BLOCK_3',1,zhook_handle)
235 IF (lhook) CALL dr_hook('SFX_XIOS_SEND_BLOCK_4',0,zhook_handle)
236 
237 
238  IF ( iempty == 0 ) THEN
239  ! The fields table is full. Allocate a new one and copy the content
240  IF (isize > imaxsize) THEN
241  CALL abor1_sfx("SFX_XIOS_SEND_BLOCK: MAX BUFFER ENTRIES NUMBER WAS REACHED")
242  ENDIF
243  !
244  ALLOCATE(yltemp(isize))
245  yltemp = ylfields
246  DEALLOCATE(ylfields)
247  !
248  ALLOCATE(ylfields(isize+incr))
249  ylfields(1:isize) = yltemp(1:isize)
250  DEALLOCATE(yltemp)
251  !
252  ylfields(isize+1:isize+incr)%YLNAME = ''
253  !
254  iempty = isize+1
255  isize = isize+incr
256  !
257  ENDIF
258  !
259 IF (lhook) CALL dr_hook('SFX_XIOS_SEND_BLOCK_4',1,zhook_handle)
260 IF (lhook) CALL dr_hook('SFX_XIOS_SEND_BLOCK_5',0,zhook_handle)
261 
262  ! Record the new field attributes (not its data)
263  !
264  ylf => ylfields(iempty)
265  ylf%YLNAME = trim(yltag)
266  !
267  CALL xios_is_defined_field_attr(yltag, grid_ref=glisdef)
268  IF (glisdef) THEN
269  CALL xios_get_field_attr(yltag, grid_ref=ylgrid)
270  IF (ylgrid(1:4)=='FULL') THEN
271  yldomain='FULL'
272  ELSEIF (ylgrid(1:3)=='SEA') THEN
273  yldomain='SEA'
274  ELSEIF (ylgrid(1:5)=='WATER') THEN
275  yldomain='WATER'
276  ELSEIF (ylgrid(1:6)=='NATURE') THEN
277  yldomain='NATURE'
278  ELSEIF (ylgrid(1:4)=='TOWN') THEN
279  yldomain='TOWN'
280  ENDIF
281  ELSE
282  CALL xios_is_defined_field_attr(yltag, domain_ref=glisdef)
283  IF (glisdef) THEN
284  CALL xios_get_field_attr(yltag, domain_ref=yldomain)
285  ELSE
286  CALL abor1_sfx('SFX_XIOS_SEND_BLOCK : FIELD '//trim(yltag)//' HAS NO DOMAIN')
287  ENDIF
288  ENDIF
289  !
290  CALL xios_get_domain_attr(yldomain, data_ni=iidim)
291  !
292  ylf%ISIZEMAX = iidim
293  !
294 IF (lhook) CALL dr_hook('SFX_XIOS_SEND_BLOCK_5',1,zhook_handle)
295 IF (lhook) CALL dr_hook('SFX_XIOS_SEND_BLOCK_6',0,zhook_handle)
296 
297  infields = 0
298  IF (PRESENT(pfield)) THEN
299  ylf%ILEV = 1
300  ylf%ILEV2 = 1
301  ylf%INDIM = 1
302  infields = infields+1
303  ENDIF
304  IF (PRESENT(pfield2)) THEN
305  ylf%ILEV = SIZE(pfield2,2)
306  ylf%ILEV2 = 1
307  ylf%INDIM = 2
308  infields = infields+1
309  ENDIF
310  IF (PRESENT(pfield3)) THEN
311  ylf%ILEV = SIZE(pfield3,2)
312  ylf%ILEV2 = SIZE(pfield3,3)
313  ylf%INDIM = 3
314  infields = infields+1
315  ENDIF
316  IF (infields /= 1 ) &
317  CALL abor1_sfx('SFX_XIOS_SEND_BLOCK : TOO FEW OR MANY PFIELDx ARGS FOR '//hdtag)
318  ALLOCATE(ylf%ZFIELD(ylf%ISIZEMAX,ylf%ILEV,ylf%ILEV2))
319  ylf%ISIZE = 0
320  ylf%IBLOCK = 0
321  !
322 IF (lhook) CALL dr_hook('SFX_XIOS_SEND_BLOCK_6',1,zhook_handle)
323 
324  ENDIF
325  !
326 ELSE
327  !
328  ylf => ylfields(il)
329  !
330 ENDIF
331 !
332 IF (lxios_def_closed) THEN
333  !
334  ! Check consistency between calls : discarded for efficiency purpose
335  !IF (ILEV .NE. YLF%ILEV) THEN
336  ! ! CALL ABOR1_SFX('SFX_XIOS_SEND_BLOCK : INCONSISTENT LEVELS # FOR '//YLTAG)
337  !ENDIF
338  !
339  ! Allocate the data buffer if needed
340  !
341 IF (lhook) CALL dr_hook('SFX_XIOS_SEND_BLOCK_7',0,zhook_handle)
342  IF (.NOT. ALLOCATED(ylf%ZFIELD)) THEN
343  ALLOCATE(ylf%ZFIELD(ylf%ISIZEMAX,ylf%ILEV,ylf%ILEV2))
344  ENDIF
345  !
346  ! Add the block data to the field buffer and send the field if it is
347  ! complete
348  !
349  IF (ylf%INDIM ==1 ) THEN
350  itake=SIZE(pfield)
351  ELSEIF (ylf%INDIM ==2 ) THEN
352  itake=SIZE(pfield2,1)
353  ELSEIF (ylf%INDIM ==3 ) THEN
354  itake=SIZE(pfield3,1)
355  ENDIF
356  !
357  ylf%IBLOCK = ylf%IBLOCK+1
358  IF ((ylf%ISIZE + itake) > ylf%ISIZEMAX) THEN
359  ! xxx a modifier : le dernier blc arpege arrive avec taille NPROMA
360  IF (ylf%IBLOCK .NE. nblock) THEN
361  CALL abor1_sfx("SFX_XIOS_SEND_BLOCK: FIELD "//trim(yltag)//&
362  " OVERFLOWS - CHECK ITS DECLARATION TO XIOS (MAYBE TWO INCONSISTENT DECLARATIONS ?)")
363  ENDIF
364  itake = ylf%ISIZEMAX - ylf%ISIZE
365  ENDIF
366  ! Store the field and update its size
367  IF (itake > 0 ) THEN
368  IF (ylf%INDIM==1) THEN
369  ylf%ZFIELD(ylf%ISIZE+1:ylf%ISIZE+itake,1,1) = pfield(1:itake)
370  ELSEIF (ylf%INDIM==2) THEN
371  ylf%ZFIELD(ylf%ISIZE+1:ylf%ISIZE+itake,:,1) = pfield2(1:itake,:)
372  ELSEIF (ylf%INDIM==3) THEN
373  ylf%ZFIELD(ylf%ISIZE+1:ylf%ISIZE+itake,:,:) = pfield3(1:itake,:,:)
374  ENDIF
375  ELSEIF ( itake < 0 ) THEN
376  CALL abor1_sfx('SFX_XIOS_SEND_BLOCK :isizemax < isize')
377  ENDIF
378  !
379  ylf%ISIZE = ylf%ISIZE + itake
380  !
381 IF (lhook) CALL dr_hook('SFX_XIOS_SEND_BLOCK_7',1,zhook_handle)
382 IF (lhook) CALL dr_hook('SFX_XIOS_SEND_BLOCK_8',0,zhook_handle)
383  IF (ylf%IBLOCK==nblock) THEN
384  ! Send field and clears the buffer (incl. de-allocation)
385  IF (ylf%INDIM==1) THEN
386  CALL xios_send_field(trim(yltag),ylf%ZFIELD(:,1,1))
387  ELSEIF (ylf%INDIM==2) THEN
388  CALL xios_send_field(trim(yltag),ylf%ZFIELD(:,:,1))
389  ELSEIF (ylf%INDIM==3) THEN
390  CALL xios_send_field(trim(yltag),ylf%ZFIELD(:,:,:))
391  ENDIF
392  ylf%IBLOCK = 0
393  ylf%ISIZE = 0
394  DEALLOCATE(ylf%ZFIELD)
395  ENDIF
396 IF (lhook) CALL dr_hook('SFX_XIOS_SEND_BLOCK_8',1,zhook_handle)
397 ENDIF
398 !
399 !$OMP END SINGLE
400 !
401 IF (ALLOCATED(ylfields)) DEALLOCATE(ylfields)
402 !
403 #endif
404 !
405 END SUBROUTINE sfx_xios_send_block
static const char * trim(const char *name, int *n)
Definition: drhook.c:2383
integer, parameter jpim
Definition: parkind1.F90:13
logical lxios
Definition: modd_xios.F90:41
subroutine abor1_sfx(YTEXT)
Definition: abor1_sfx.F90:7
logical lxios_def_closed
Definition: modd_xios.F90:54
integer, parameter jprb
Definition: parkind1.F90:32
subroutine sfx_xios_send_block(HDTAG, PFIELD, PFIELD2, PFIELD3, HDOMAIN, HAXIS, HAXIS2, HDCOMMENT, KFREQOP)
logical lhook
Definition: yomhook.F90:15
subroutine sfx_xios_declare_field(HREC, HDOMAIN, HAXIS, KLEV, HAXIS2, KLEV2, HCOMMENT, KFREQOP)
integer nblock
Definition: modd_xios.F90:57
integer ntimestep
Definition: modd_xios.F90:56