source: XIOS3/trunk/src/test/generic_testcase.f90 @ 2542

Last change on this file since 2542 was 2541, checked in by ymipsl, 10 months ago

for compatibility with ferret :

  • change vertical axis units from Pa to mb
  • invert lower an upper bounds for vertical axis (decreasing values)

YM

  • Property svn:executable set to *
File size: 89.8 KB
Line 
1PROGRAM generic_testcase
2  USE xios
3  USE mod_wait
4  IMPLICIT NONE
5  INCLUDE "mpif.h"
6  INTEGER,PARAMETER :: unit=10
7  INTEGER,PARAMETER :: len_str=255
8  INTEGER :: ierr
9
10  INTEGER :: nb_proc_atm
11  INTEGER :: nb_proc_oce
12  INTEGER :: nb_proc_surf
13  INTEGER :: nb_proc_server
14  CHARACTER(LEN=len_str)  :: proc_distribution
15  CHARACTER(LEN=len_str)  :: start_date
16  CHARACTER(LEN=len_str)  :: duration
17  DOUBLE PRECISION        :: sypd
18  NAMELIST /params_run/    nb_proc_atm, nb_proc_surf, nb_proc_oce, & 
19                           duration, sypd, start_date, proc_distribution
20
21
22  TYPE tmodel_params
23    CHARACTER(len_str)  :: timestep=""
24    CHARACTER(len_str)  :: domain=""
25    DOUBLE PRECISION    :: domain_proc_frac
26    INTEGER             :: domain_proc_n
27    CHARACTER(len_str)  :: axis=""
28    DOUBLE PRECISION    :: axis_proc_frac
29    INTEGER             :: axis_proc_n
30    INTEGER             :: ensemble_proc_n
31    INTEGER             :: ni 
32    INTEGER             :: nj 
33    INTEGER             :: nlev
34    CHARACTER(len_str)  :: init_field2D=""
35    DOUBLE PRECISION    :: pressure_factor
36    LOGICAL             :: domain_mask 
37    CHARACTER(len_str)  :: domain_mask_type=""
38    LOGICAL             :: scalar_mask
39    CHARACTER(len_str) :: scalar_mask_type=""
40    LOGICAL :: axis_mask
41    LOGICAL :: mask3d
42    INTEGER             :: field_sub_freq 
43    INTEGER             :: field_sub_offset
44  END TYPE  tmodel_params
45
46
47
48  CHARACTER(len_str)  :: timestep_atm
49  CHARACTER(len_str)  :: domain_atm 
50  CHARACTER(len_str)  :: axis_atm 
51  INTEGER             :: ni_atm 
52  INTEGER             :: nj_atm 
53  INTEGER             :: nlev_atm
54  CHARACTER(len_str)  :: init_field2D_atm 
55 
56 
57  LOGICAL :: i_am_atm, i_am_oce, i_am_surf, i_am_server
58  INTEGER :: rank, size_loc
59  INTEGER :: nb_procs(4)
60  LOGICAL :: who_i_am(4)
61  INTEGER :: provided
62   
63  OPEN(unit=unit, file='param.def',status='old',iostat=ierr)
64  nb_proc_atm=1
65  nb_proc_oce=0 
66  nb_proc_surf=0
67  duration="1d"
68  sypd=10000
69  start_date="2018-01-01"
70  proc_distribution="contiguous"
71  READ (unit, nml=params_run)
72  CLOSE(unit)
73!!! MPI Initialization
74
75  CALL MPI_INIT_THREAD(MPI_THREAD_SERIALIZED, provided, ierr)
76
77  CALL init_wait
78  CALL MPI_COMM_RANK(MPI_COMM_WORLD,rank,ierr)
79  CALL MPI_COMM_SIZE(MPI_COMM_WORLD,size_loc,ierr)
80  if (size_loc < nb_proc_atm + nb_proc_oce + nb_proc_surf) then
81     PRINT *,"inconsistency : size=",size_loc," nb_proc_atm=",nb_proc_atm,&
82          " nb_proc_oce=",nb_proc_oce," nb_proc_surf=",nb_proc_surf
83     CALL MPI_ABORT()
84  endif
85
86  nb_proc_server=size_loc-(nb_proc_atm + nb_proc_oce + nb_proc_surf)
87  i_am_atm=.FALSE. ; i_am_oce=.FALSE. ; i_am_surf=.FALSE. ; i_am_server=.FALSE. 
88
89  IF (proc_distribution=="contiguous") THEN
90
91   ! First ranks are dedicated to Atm, next to Ocean, next to Surf, last to Server
92
93    IF (rank < nb_proc_atm) THEN
94      i_am_atm=.TRUE. 
95    ELSE IF (rank < nb_proc_atm+nb_proc_oce) THEN
96      i_am_oce=.TRUE. 
97    ELSE IF (rank < nb_proc_atm+nb_proc_oce+nb_proc_surf) THEN
98      i_am_surf=.TRUE. 
99    ELSE
100      i_am_server=.TRUE. 
101    ENDIF ;
102  ELSE IF (proc_distribution=="cyclic") THEN
103   ! server ranks are dispatched all along the partition
104    nb_procs(1)=nb_proc_atm ; nb_procs(2)=nb_proc_oce ; nb_procs(3)=nb_proc_surf ; nb_procs(4)=nb_proc_server
105    CALL compute_cyclic_distribution(rank, nb_procs, who_i_am )
106    i_am_atm=who_i_am(1)
107    i_am_oce=who_i_am(2)
108    i_am_surf=who_i_am(3)
109    i_am_server=who_i_am(4)
110  ENDIF
111 
112 
113  IF (i_am_server) THEN
114    CALL xios_init_server()
115 
116  ELSE
117
118    IF (i_am_atm) CALL model("atm")
119    IF (i_am_oce) CALL model("oce")
120    IF (i_am_surf) CALL model("surf")
121 
122    CALL xios_finalize()
123  ENDIF
124
125  CALL MPI_FINALIZE(ierr)
126 
127CONTAINS
128
129  SUBROUTINE model(model_id)
130  IMPLICIT NONE
131    CHARACTER(LEN=*) :: model_id
132    TYPE(tmodel_params) :: params, other_params
133    TYPE(xios_context) :: ctx_hdl
134    INTEGER :: comm
135    TYPE(xios_date)  :: cdate, edate
136    TYPE(xios_duration)  :: dtime
137    INTEGER :: rank
138    INTEGER :: size_loc
139    DOUBLE PRECISION :: timestep_in_seconds, simulated_seconds_per_seconds, elapsed_per_timestep
140    INTEGER :: ts
141
142    DOUBLE PRECISION, POINTER :: lon(:)
143    DOUBLE PRECISION, POINTER :: lat(:)
144    DOUBLE PRECISION, POINTER :: axis_value(:)
145    LOGICAL, POINTER          :: domain_mask(:)
146    INTEGER, POINTER          :: domain_index(:)
147    LOGICAL, POINTER          :: axis_mask(:)
148    LOGICAL                   :: scalar_mask
149    INTEGER, POINTER          :: axis_index(:)
150    DOUBLE PRECISION, POINTER :: ensemble_value(:)
151   
152    DOUBLE PRECISION, POINTER :: X_lon(:)
153    DOUBLE PRECISION, POINTER :: X_lat(:)
154    LOGICAL, POINTER          :: X_mask(:)
155    INTEGER, POINTER          :: X_index(:)
156
157    DOUBLE PRECISION, POINTER :: Y_lon(:)
158    DOUBLE PRECISION, POINTER :: Y_lat(:)
159    LOGICAL, POINTER          :: Y_mask(:)
160    INTEGER, POINTER          :: Y_index(:)
161               
162    DOUBLE PRECISION, POINTER :: field2D_init(:)
163    DOUBLE PRECISION, POINTER :: fieldX_init(:)
164    DOUBLE PRECISION, POINTER :: fieldY_init(:)
165    DOUBLE PRECISION, POINTER :: fieldXY_init(:,:)
166
167    DOUBLE PRECISION, POINTER :: field2D(:), other_field2D(:)
168    DOUBLE PRECISION          :: field0D, other_field0D
169    DOUBLE PRECISION, POINTER :: field_X(:), other_field_X(:)
170    DOUBLE PRECISION, POINTER :: field_Y(:), other_field_Y(:)
171    DOUBLE PRECISION, POINTER :: field_Z(:), other_field_Z(:)
172    DOUBLE PRECISION, POINTER :: field_XY(:,:), other_field_XY(:,:)
173    DOUBLE PRECISION, POINTER :: field_XYZ(:,:,:), other_field_XYZ(:,:,:)
174    DOUBLE PRECISION, POINTER :: field_XZ(:,:), other_field_XZ(:,:)
175    DOUBLE PRECISION, POINTER :: field_YZ(:,:), other_field_YZ(:,:)
176   
177    DOUBLE PRECISION, POINTER :: field2D_sub(:), other_field2D_sub(:)
178    DOUBLE PRECISION, POINTER :: field3D(:,:), other_field3D(:,:)
179    DOUBLE PRECISION, POINTER :: field3D_sub(:,:), other_field3D_sub(:,:)
180    DOUBLE PRECISION, POINTER :: field3D_recv(:,:), other_field3D_recv(:,:)
181    DOUBLE PRECISION, POINTER :: pressure(:,:), other_pressure(:,:)
182
183    DOUBLE PRECISION, POINTER :: field2D_W(:,:), other_field2D_W(:,:)
184    DOUBLE PRECISION, POINTER :: field0D_W(:), other_field0D_W(:)
185    DOUBLE PRECISION, POINTER :: field_XW(:,:), other_field_XW(:,:)
186    DOUBLE PRECISION, POINTER :: field_YW(:,:), other_field_YW(:,:)
187    DOUBLE PRECISION, POINTER :: field_ZW(:,:), other_field_ZW(:,:)
188    DOUBLE PRECISION, POINTER :: field_XYW(:,:,:), other_field_XYW(:,:,:)
189    DOUBLE PRECISION, POINTER :: field_XYZW(:,:,:,:), other_field_XYZW(:,:,:,:)
190    DOUBLE PRECISION, POINTER :: field_XZW(:,:,:), other_field_XZW(:,:,:)
191    DOUBLE PRECISION, POINTER :: field_YZW(:,:,:), other_field_YZW(:,:,:)
192   
193    DOUBLE PRECISION, POINTER :: field2D_sub_W(:,:), other_field2D_sub_W(:,:)
194    DOUBLE PRECISION, POINTER :: field3D_W(:,:,:), other_field3D_W(:,:,:)
195    DOUBLE PRECISION, POINTER :: field3D_sub_W(:,:,:), other_field3D_sub_W(:,:,:)
196    DOUBLE PRECISION, POINTER :: field3D_recv_W(:,:,:), other_field3D_recv_W(:,:,:)
197    DOUBLE PRECISION, POINTER :: pressure_W(:,:,:), other_pressure_W(:,:,:)
198
199
200
201   
202    TYPE(xios_duration) :: freq_op_recv, freq_offset_recv
203    INTEGER :: ni,nj,nk
204    INTEGER :: i,j,k,xy,x,y,z,w
205    DOUBLE PRECISION :: scale,dist
206    LOGICAL :: ok
207    INTEGER :: ierr     
208
209    LOGICAL :: ok_field0D, ok_field2D, ok_field3D, ok_pressure, ok_field2D_sub, ok_field3D_sub,ok_field3D_recv, ok_field3D_send
210    LOGICAL :: ok_field_X, ok_field_Y, ok_field_XY, ok_field_Z, ok_field_XYZ, ok_field_XZ, ok_field_YZ
211    LOGICAL :: ok_field0D_W, ok_field2D_W, ok_field3D_W, ok_pressure_W, ok_field2D_sub_W, ok_field3D_sub_W,ok_field3D_recv_W, ok_field3D_send_W
212    LOGICAL :: ok_field_XW, ok_field_YW, ok_field_XYW, ok_field_ZW, ok_field_XYZW, ok_field_XZW, ok_field_YZW
213
214    LOGICAL :: ok_other_field0D, ok_other_field2D, ok_other_field3D, ok_other_pressure, ok_other_field2D_sub, ok_other_field3D_sub,ok_other_field3D_recv, ok_other_field3D_send
215    LOGICAL :: ok_other_field_X, ok_other_field_Y, ok_other_field_XY, ok_other_field_Z, ok_other_field_XYZ, ok_other_field_XZ, ok_other_field_YZ
216    LOGICAL :: ok_other_field0D_W, ok_other_field2D_W, ok_other_field3D_W, ok_other_pressure_W, ok_other_field2D_sub_W, ok_other_field3D_sub_W,ok_other_field3D_recv_W, ok_other_field3D_send_W
217    LOGICAL :: ok_other_field_XW, ok_other_field_YW, ok_other_field_XYW, ok_other_field_ZW, ok_other_field_XYZW, ok_other_field_XZW, ok_other_field_YZW
218
219    TYPE(xios_domain)  :: domain_handle
220   
221      !! XIOS Initialization (get the local communicator)
222    CALL xios_initialize(trim(model_id),return_comm=comm)
223    CALL MPI_COMM_RANK(comm,rank,ierr)
224    CALL MPI_COMM_SIZE(comm,size_loc,ierr)
225    CALL xios_context_initialize(trim(model_id),comm)
226    CALL xios_get_handle(trim(model_id),ctx_hdl)
227    CALL xios_set_current_context(ctx_hdl)
228   
229    CALL init_model_params('',params)
230    CALL init_model_params('other_',other_params)
231   !!! Definition du découpage domain/axis
232
233   
234   !!! Definition de la start date et du timestep
235    CALL xios_set_start_date(xios_date_convert_from_string(start_date//" 00:00:00"))
236    dtime=xios_duration_convert_from_string(TRIM(params%timestep))
237    CALL xios_set_timestep(timestep=dtime)
238
239     !!! Calcul de temps elaps par seconde pour respecter le SYPD (hyp : pas de delai d'I/O)
240    CALL xios_get_start_date(cdate)
241    edate=cdate+xios_duration_convert_from_string(TRIM(duration))
242    timestep_in_seconds=xios_date_convert_to_seconds(cdate+dtime) - xios_date_convert_to_seconds(cdate)
243    simulated_seconds_per_seconds=sypd * 365 
244    elapsed_per_timestep=timestep_in_seconds/simulated_seconds_per_seconds ! in seconds
245
246
247!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
248!!!             standard initialisation of domain, axis, grid, field                               !
249!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
250
251    CALL init_domain("domain", comm, params, ni, nj, lon, lat, domain_mask, domain_index, &
252                                                     X_lon, X_lat, X_mask, X_index,       &
253                                                     Y_lon, Y_lat, Y_mask, Y_index)
254                                                     
255    CALL init_axis("axis", comm, params, axis_value, axis_mask, axis_index)
256    CALL init_scalar("scalar", comm, params,  scalar_mask)
257    CALL init_ensemble("ensemble", comm, params, ensemble_value)
258
259    CALL set_mask3d("grid3D",params, ni, nj, lon, lat , axis_value)
260     !!! Fin de la definition du contexte
261
262    ok_field3D_recv=xios_is_valid_field("field3D_recv").AND.xios_is_valid_field("field3D_resend") ;
263    IF (ok_field3D_recv) THEN
264      CALL xios_is_defined_field_attr("field3D_recv",freq_op=ok)
265      IF (ok) THEN
266        CALL xios_get_field_attr("field3D_recv",freq_op=freq_op_recv)
267       ELSE
268         freq_op_recv%timestep=1
269         CALL xios_set_field_attr("field3D_recv",freq_op=freq_op_recv)
270      ENDIF
271      CALL xios_is_defined_field_attr("field3D_recv",freq_offset=ok)
272      IF (ok) THEN
273        CALL xios_get_field_attr("field3D_recv",freq_offset=freq_offset_recv)
274      ELSE
275         freq_offset_recv%timestep=0
276         CALL xios_set_field_attr("field3D_recv",freq_op=freq_op_recv)
277      ENDIF
278      CALL xios_set_field_attr("field3D_resend",freq_op=freq_op_recv,freq_offset=freq_offset_recv)
279    ENDIF
280   
281    ok_field3D_recv_W=xios_is_valid_field("field3D_recv_W").AND.xios_is_valid_field("field3D_resend_W") ;
282    IF (ok_field3D_recv_W) THEN
283      CALL xios_is_defined_field_attr("field3D_recv_W",freq_op=ok)
284      IF (ok) THEN
285        CALL xios_get_field_attr("field3D_recv_W",freq_op=freq_op_recv)
286       ELSE
287         freq_op_recv%timestep=1
288         CALL xios_set_field_attr("field3D_recv_W",freq_op=freq_op_recv)
289      ENDIF
290      CALL xios_is_defined_field_attr("field3D_recv_W",freq_offset=ok)
291      IF (ok) THEN
292        CALL xios_get_field_attr("field3D_recv_W",freq_offset=freq_offset_recv)
293      ELSE
294         freq_offset_recv%timestep=0
295         CALL xios_set_field_attr("field3D_recv_W",freq_op=freq_op_recv)
296      ENDIF
297      CALL xios_set_field_attr("field3D_resend_W",freq_op=freq_op_recv,freq_offset=freq_offset_recv)
298    ENDIF
299
300
301    CALL init_field2D(comm, params, lon, lat, domain_mask, field2D_init, &
302                      x_lon, x_lat, x_mask, fieldX_init, y_lon, y_lat, y_mask, fieldY_init, fieldXY_init)
303
304    xy=size(domain_index)
305    x=size(X_index)
306    y=size(Y_index)
307    z=size(axis_index)
308    w=size(ensemble_value)
309
310    ALLOCATE(field2D(0:xy-1))
311    ALLOCATE(field3D(0:xy-1,0:z-1))
312    ALLOCATE(pressure(0:xy-1,0:z-1))
313    ALLOCATE(field3D_recv(0:xy-1,0:z-1))
314    ALLOCATE(field_Z(0:z-1))
315    ALLOCATE(field_X(0:x-1))
316    ALLOCATE(field_Y(0:y-1))
317    ALLOCATE(field_XY(0:x-1,0:y-1))
318    ALLOCATE(field_XYZ(0:x-1,0:y-1,0:z-1))
319    ALLOCATE(field_XZ(0:x-1,0:z-1))
320    ALLOCATE(field_YZ(0:y-1,0:z-1))
321
322    ALLOCATE(field2D_W(0:xy-1,0:w-1))
323    ALLOCATE(field3D_W(0:xy-1,0:z-1,0:w-1))
324    ALLOCATE(pressure_W(0:xy-1,0:z-1,0:w-1))
325    ALLOCATE(field3D_recv_W(0:xy-1,0:z-1,0:w-1))
326    ALLOCATE(field_ZW(0:z-1,0:w-1))
327    ALLOCATE(field_XW(0:x-1,0:w-1))
328    ALLOCATE(field_YW(0:y-1,0:w-1))
329    ALLOCATE(field_XYW(0:x-1,0:y-1,0:w-1))
330    ALLOCATE(field_XYZW(0:x-1,0:y-1,0:z-1,0:w-1))
331    ALLOCATE(field_XZW(0:x-1,0:z-1,0:w-1))
332    ALLOCATE(field_YZW(0:y-1,0:z-1,0:w-1))
333    ALLOCATE(field0D_W(0:w-1))
334   
335
336
337    DO i=0,xy-1
338      IF (domain_index(i)/=-1) THEN
339        field2D(i)=field2D_init(domain_index(i))
340      ENDIF
341    ENDDO
342
343    DO i=0,x-1
344      IF (X_index(i)/=-1) THEN
345        field_X(i)=fieldX_init(X_index(i))
346      ENDIF
347    ENDDO
348
349    DO i=0,y-1
350      IF (Y_index(i)/=-1) THEN
351        field_Y(i)=fieldY_init(Y_index(i))
352      ENDIF
353    ENDDO
354
355    DO j=0,y-1
356      DO i=0,x-1
357        IF (Y_index(j)/=-1 .AND. X_index(i)/=-1) THEN
358          field_XY(i,j)=fieldXY_init(X_index(i),Y_index(j))
359        ENDIF
360      ENDDO
361    ENDDO
362
363    DO i=0,z-1
364      IF (axis_index(i)/=-1) THEN
365        k=axis_index(i)
366        IF (axis_mask(k)) THEN
367          field_Z(i)=axis_value(axis_index(k))
368          field3D(:,i)=field2D(:)*axis_value(axis_index(k))
369          field_XYZ(:,:,i)=field_XY(:,:)*axis_value(axis_index(k))
370          field_XZ(:,i)=field_X(:)*axis_value(axis_index(k))
371          field_YZ(:,i)=field_Y(:)*axis_value(axis_index(k))
372        ENDIF
373      ENDIF
374    ENDDO
375         
376    pressure=1e20
377    DO j=0,z-1
378      pressure(:,j)=axis_value(j)*100000 ; ! Pa
379      DO i=0,xy-1
380        IF (domain_index(i)/=-1) THEN
381          k=domain_index(i)
382          IF (domain_mask(k)) THEN
383            dist=sqrt((lat(k)/90.)**2+(lon(k)/180.)**2) ;
384            pressure(i,j)=pressure(i,j)*(1+params%pressure_factor*exp(-(4*dist)**2))
385          ENDIF
386        ENDIF
387      ENDDO
388    ENDDO
389   
390    field0D=1
391
392
393    field2D_W(:,0) = field2D(:)*(1+0.1*ensemble_value(0))
394    field3D_W(:,:,0)= field3D(:,:)*(1+0.1*ensemble_value(0))
395    pressure_W(:,:,0) = pressure(:,:)*(1+0.1*ensemble_value(0))
396    field_XW(:,0) = field_X(:)*(1+0.1*ensemble_value(0))
397    field_YW(:,0) = field_Y(:)*(1+0.1*ensemble_value(0))
398    field_XYW(:,:,0) = field_XY(:,:)*(1+0.1*ensemble_value(0))
399    field_ZW(:,0) = field_Z(:)*(1+0.1*ensemble_value(0))
400    field_XYZW(:,:,:,0) = field_XYZ(:,:,:)*(1+0.1*ensemble_value(0))
401    field_XZW(:,:,0) = field_XZ(:,:)*(1+0.1*ensemble_value(0))
402    field_YZW(:,:,0) = field_YZ(:,:)*(1+0.1*ensemble_value(0))
403    field0D_W(0) = field0D*(1+0.1*ensemble_value(0))
404   
405    ok_field2D=xios_is_valid_field("field2D") ;
406    ok_field3D=xios_is_valid_field("field3D") ;
407    ok_pressure=xios_is_valid_field("pressure") ;
408    ok_field2D_sub=xios_is_valid_field("field2D_sub") ;
409    ok_field3D_sub=xios_is_valid_field("field3D_sub") ;
410    ok_field_X=xios_is_valid_field("field_X") ;
411    ok_field_Y=xios_is_valid_field("field_Y") ;
412    ok_field_XY=xios_is_valid_field("field_XY") ;
413    ok_field_Z=xios_is_valid_field("field_Z") ; 
414    ok_field_XYZ=xios_is_valid_field("field_XYZ") ;
415    ok_field_XZ=xios_is_valid_field("field_XZ") ;
416    ok_field_YZ=xios_is_valid_field("field_YZ") ;
417    ok_field0D=xios_is_valid_field("field0D") ;
418
419    ok_field2D_W=xios_is_valid_field("field2D_W") ;
420    ok_field3D_W=xios_is_valid_field("field3D_W") ;
421    ok_pressure_W=xios_is_valid_field("pressure_W") ;
422    ok_field2D_sub_W=xios_is_valid_field("field2D_sub_W") ;
423    ok_field3D_sub_W=xios_is_valid_field("field3D_sub_W") ;
424    ok_field_XW=xios_is_valid_field("field_XW") ;
425    ok_field_YW=xios_is_valid_field("field_YW") ;
426    ok_field_XYW=xios_is_valid_field("field_XYW") ;
427    ok_field_ZW=xios_is_valid_field("field_ZW") ; 
428    ok_field_XYZW=xios_is_valid_field("field_XYZW") ;
429    ok_field_XZW=xios_is_valid_field("field_XZW") ;
430    ok_field_YZW=xios_is_valid_field("field_YZW") ;
431    ok_field0D_W=xios_is_valid_field("field0D_W") ;
432
433
434
435    IF (ASSOCIATED(lon)) DEALLOCATE(lon)
436    IF (ASSOCIATED(lat)) DEALLOCATE(lat)
437    IF (ASSOCIATED(axis_value)) DEALLOCATE(axis_value)
438    IF (ASSOCIATED(domain_mask)) DEALLOCATE(domain_mask)
439    IF (ASSOCIATED(domain_index)) DEALLOCATE(domain_index)
440    IF (ASSOCIATED(axis_mask)) DEALLOCATE(axis_mask)
441    IF (ASSOCIATED(axis_index)) DEALLOCATE(axis_index)
442    IF (ASSOCIATED(ensemble_value)) DEALLOCATE(ensemble_value)
443    IF (ASSOCIATED(X_lon)) DEALLOCATE(X_lon)
444    IF (ASSOCIATED(X_lat)) DEALLOCATE(X_lat)
445    IF (ASSOCIATED(X_mask)) DEALLOCATE(X_mask)
446    IF (ASSOCIATED(X_index)) DEALLOCATE(X_index)
447    IF (ASSOCIATED(Y_lon)) DEALLOCATE(Y_lon)
448    IF (ASSOCIATED(Y_lat)) DEALLOCATE(Y_lat)
449    IF (ASSOCIATED(Y_mask)) DEALLOCATE(Y_mask)
450    IF (ASSOCIATED(Y_index)) DEALLOCATE(Y_index)
451    IF (ASSOCIATED(field2D_init)) DEALLOCATE(field2D_init)
452    IF (ASSOCIATED(fieldX_init)) DEALLOCATE(fieldX_init)
453    IF (ASSOCIATED(fieldY_init)) DEALLOCATE(fieldY_init)
454    IF (ASSOCIATED(fieldXY_init)) DEALLOCATE(fieldXY_init)
455
456
457!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
458!              duplicated section for other_                    !
459!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
460
461    CALL init_domain("other_domain", comm, other_params, ni, nj, lon, lat, domain_mask, domain_index, &
462                                                     X_lon, X_lat, X_mask, X_index,       &
463                                                     Y_lon, Y_lat, Y_mask, Y_index)
464                                                     
465    CALL init_axis("other_axis", comm, other_params, axis_value, axis_mask, axis_index)
466    CALL init_scalar("other_scalar", comm, params, scalar_mask)
467    CALL init_ensemble("other_ensemble", comm, other_params, ensemble_value)
468
469    CALL set_mask3d("other_grid3D",other_params, ni, nj, lon, lat , axis_value)
470     !!! Fin de la definition du contexte
471
472    ok_other_field3D_recv=xios_is_valid_field("other_field3D_recv").AND.xios_is_valid_field("other_field3D_resend") ;
473    IF (ok_other_field3D_recv) THEN
474      CALL xios_is_defined_field_attr("other_field3D_recv",freq_op=ok)
475      IF (ok) THEN
476        CALL xios_get_field_attr("other_field3D_recv",freq_op=freq_op_recv)
477       ELSE
478         freq_op_recv%timestep=1
479         CALL xios_set_field_attr("other_field3D_recv",freq_op=freq_op_recv)
480      ENDIF
481      CALL xios_is_defined_field_attr("other_field3D_recv",freq_offset=ok)
482      IF (ok) THEN
483        CALL xios_get_field_attr("other_field3D_recv",freq_offset=freq_offset_recv)
484      ELSE
485         freq_offset_recv%timestep=0
486         CALL xios_set_field_attr("other_field3D_recv",freq_op=freq_op_recv)
487      ENDIF
488      CALL xios_set_field_attr("other_field3D_resend",freq_op=freq_op_recv,freq_offset=freq_offset_recv)
489    ENDIF
490   
491    ok_other_field3D_recv_W=xios_is_valid_field("other_field3D_recv_W").AND.xios_is_valid_field("other_field3D_resend_W") ;
492    IF (ok_other_field3D_recv_W) THEN
493      CALL xios_is_defined_field_attr("other_field3D_recv_W",freq_op=ok)
494      IF (ok) THEN
495        CALL xios_get_field_attr("other_field3D_recv_W",freq_op=freq_op_recv)
496       ELSE
497         freq_op_recv%timestep=1
498         CALL xios_set_field_attr("other_field3D_recv_W",freq_op=freq_op_recv)
499      ENDIF
500      CALL xios_is_defined_field_attr("other_field3D_recv_W",freq_offset=ok)
501      IF (ok) THEN
502        CALL xios_get_field_attr("other_field3D_recv_W",freq_offset=freq_offset_recv)
503      ELSE
504         freq_offset_recv%timestep=0
505         CALL xios_set_field_attr("other_field3D_recv_W",freq_op=freq_op_recv)
506      ENDIF
507      CALL xios_set_field_attr("other_field3D_resend_W",freq_op=freq_op_recv,freq_offset=freq_offset_recv)
508    ENDIF
509
510
511    CALL init_field2D(comm, other_params, lon, lat, domain_mask, field2D_init, &
512                      x_lon, x_lat, x_mask, fieldX_init, y_lon, y_lat, y_mask, fieldY_init, fieldXY_init)
513
514    xy=size(domain_index)
515    x=size(X_index)
516    y=size(Y_index)
517    z=size(axis_index)
518    w=size(ensemble_value)
519
520    ALLOCATE(other_field2D(0:xy-1))
521    ALLOCATE(other_field3D(0:xy-1,0:z-1))
522    ALLOCATE(other_pressure(0:xy-1,0:z-1))
523    ALLOCATE(other_field3D_recv(0:xy-1,0:z-1))
524    ALLOCATE(other_field_Z(0:z-1))
525    ALLOCATE(other_field_X(0:x-1))
526    ALLOCATE(other_field_Y(0:y-1))
527    ALLOCATE(other_field_XY(0:x-1,0:y-1))
528    ALLOCATE(other_field_XYZ(0:x-1,0:y-1,0:z-1))
529    ALLOCATE(other_field_XZ(0:x-1,0:z-1))
530    ALLOCATE(other_field_YZ(0:y-1,0:z-1))
531
532    ALLOCATE(other_field2D_W(0:xy-1,0:w-1))
533    ALLOCATE(other_field3D_W(0:xy-1,0:z-1,0:w-1))
534    ALLOCATE(other_pressure_W(0:xy-1,0:z-1,0:w-1))
535    ALLOCATE(other_field3D_recv_W(0:xy-1,0:z-1,0:w-1))
536    ALLOCATE(other_field_ZW(0:z-1,0:w-1))
537    ALLOCATE(other_field_XW(0:x-1,0:w-1))
538    ALLOCATE(other_field_YW(0:y-1,0:w-1))
539    ALLOCATE(other_field_XYW(0:x-1,0:y-1,0:w-1))
540    ALLOCATE(other_field_XYZW(0:x-1,0:y-1,0:z-1,0:w-1))
541    ALLOCATE(other_field_XZW(0:x-1,0:z-1,0:w-1))
542    ALLOCATE(other_field_YZW(0:y-1,0:z-1,0:w-1))
543    ALLOCATE(other_field0D_W(0:w-1))
544   
545
546
547    DO i=0,xy-1
548      IF (domain_index(i)/=-1) THEN
549        other_field2D(i)=field2D_init(domain_index(i))
550      ENDIF
551    ENDDO
552
553    DO i=0,x-1
554      IF (X_index(i)/=-1) THEN
555        other_field_X(i)=fieldX_init(X_index(i))
556      ENDIF
557    ENDDO
558
559    DO i=0,y-1
560      IF (Y_index(i)/=-1) THEN
561        other_field_Y(i)=fieldY_init(Y_index(i))
562      ENDIF
563    ENDDO
564
565    DO j=0,y-1
566      DO i=0,x-1
567        IF (Y_index(j)/=-1 .AND. X_index(i)/=-1) THEN
568          other_field_XY(i,j)=fieldXY_init(X_index(i),Y_index(j))
569        ENDIF
570      ENDDO
571    ENDDO
572
573    DO i=0,z-1
574      IF (axis_index(i)/=-1) THEN
575        k=axis_index(i)
576        IF (axis_mask(k)) THEN
577          other_field_Z(i)=axis_value(axis_index(k))
578          other_field3D(:,i)=other_field2D(:)*axis_value(axis_index(k))
579          other_field_XYZ(:,:,i)=other_field_XY(:,:)*axis_value(axis_index(k))
580          other_field_XZ(:,i)=other_field_X(:)*axis_value(axis_index(k))
581          other_field_YZ(:,i)=other_field_Y(:)*axis_value(axis_index(k))
582        ENDIF
583      ENDIF
584    ENDDO
585         
586    other_pressure=1e20
587    DO j=0,z-1
588      other_pressure(:,j)=axis_value(j)*100000 ; ! Pa
589      DO i=0,xy-1
590        IF (domain_index(i)/=-1) THEN
591          k=domain_index(i)
592          IF (domain_mask(k)) THEN
593            dist=sqrt((lat(k)/90.)**2+(lon(k)/180.)**2) ;
594            other_pressure(i,j)=other_pressure(i,j)*(1+other_params%pressure_factor*exp(-(4*dist)**2))
595          ENDIF
596        ENDIF
597      ENDDO
598    ENDDO
599   
600    other_field0D = 1
601
602
603    other_field2D_W(:,0) = other_field2D(:)*(1+0.1*ensemble_value(0))
604    other_field3D_W(:,:,0)= other_field3D(:,:)*(1+0.1*ensemble_value(0))
605    other_pressure_W(:,:,0) = other_pressure(:,:)*(1+0.1*ensemble_value(0))
606    other_field_XW(:,0) = other_field_X(:)*(1+0.1*ensemble_value(0))
607    other_field_YW(:,0) = other_field_Y(:)*(1+0.1*ensemble_value(0))
608    other_field_XYW(:,:,0) = other_field_XY(:,:)*(1+0.1*ensemble_value(0))
609    other_field_ZW(:,0) = other_field_Z(:)*(1+0.1*ensemble_value(0))
610    other_field_XYZW(:,:,:,0) = other_field_XYZ(:,:,:)*(1+0.1*ensemble_value(0))
611    other_field_XZW(:,:,0) = other_field_XZ(:,:)*(1+0.1*ensemble_value(0))
612    other_field_YZW(:,:,0) = other_field_YZ(:,:)*(1+0.1*ensemble_value(0))
613    other_field0D_W(0) = other_field0D*(1+0.1*ensemble_value(0))
614   
615   
616    ok_other_field2D=xios_is_valid_field("other_field2D") ;
617    ok_other_field3D=xios_is_valid_field("other_field3D") ;
618    ok_other_pressure=xios_is_valid_field("other_pressure") ;
619    ok_other_field2D_sub=xios_is_valid_field("other_field2D_sub") ;
620    ok_other_field3D_sub=xios_is_valid_field("other_field3D_sub") ;
621    ok_other_field_X=xios_is_valid_field("other_field_X") ;
622    ok_other_field_Y=xios_is_valid_field("other_field_Y") ;
623    ok_other_field_XY=xios_is_valid_field("other_field_XY") ;
624    ok_other_field_Z=xios_is_valid_field("other_field_Z") ; 
625    ok_other_field_XYZ=xios_is_valid_field("other_field_XYZ") ;
626    ok_other_field_XZ=xios_is_valid_field("other_field_XZ") ;
627    ok_other_field_YZ=xios_is_valid_field("other_field_YZ") ;
628    ok_other_field0D=xios_is_valid_field("other_field0D") ;
629
630    ok_other_field2D_W=xios_is_valid_field("other_field2D_W") ;
631    ok_other_field3D_W=xios_is_valid_field("other_field3D_W") ;
632    ok_other_pressure_W=xios_is_valid_field("other_pressure_W") ;
633    ok_other_field2D_sub_W=xios_is_valid_field("other_field2D_sub_W") ;
634    ok_other_field3D_sub_W=xios_is_valid_field("other_field3D_sub_W") ;
635    ok_other_field_XW=xios_is_valid_field("other_field_XW") ;
636    ok_other_field_YW=xios_is_valid_field("other_field_YW") ;
637    ok_other_field_XYZW=xios_is_valid_field("other_field_XYW") ;
638    ok_other_field_ZW=xios_is_valid_field("other_field_ZW") ; 
639    ok_other_field_XYZW=xios_is_valid_field("other_field_XYZW") ;
640    ok_other_field_XZW=xios_is_valid_field("other_field_XZW") ;
641    ok_other_field_YZW=xios_is_valid_field("other_field_YZW") ;
642    ok_other_field0D_W=xios_is_valid_field("other_field0D_W") ;
643
644
645!!!!!!!!!!!!!!!!!!!!! end of duplicated section   !!!!!!!!!!!!!!!!!!!!!!!!!!
646
647    ts=1
648    cdate=cdate+dtime
649    CALL xios_close_context_definition()
650    CALL xios_set_current_context(trim(model_id))
651!    CALL xios_get_handle("field3D::domain",domain_handle)
652   
653    DO while ( cdate <= edate )
654 
655      !!! Mise a jour du pas de temps
656      CALL xios_update_calendar(ts)
657
658      IF (ok_field2D) CALL xios_send_field("field2D",field2D)
659      IF (ok_field3D) CALL xios_send_field("field3D",field3D)
660      IF (ok_pressure) CALL xios_send_field("pressure",pressure)
661      IF (ok_field_X) CALL xios_send_field("field_X",field_X)
662      IF (ok_field_Y) CALL xios_send_field("field_Y",field_Y)
663      IF (ok_field_XY) CALL xios_send_field("field_XY",field_XY)
664      IF (ok_field_Z) CALL xios_send_field("field_Z",field_Z)
665      IF (ok_field_XYZ) CALL xios_send_field("field_XYZ",field_XYZ)
666      IF (ok_field_XZ) CALL xios_send_field("field_XZ",field_XZ)
667      IF (ok_field_YZ) CALL xios_send_field("field_YZ",field_YZ)
668      IF (ok_field0D)  CALL xios_send_field("field0D",field0D)
669     
670      IF ( MOD(params%field_sub_offset+ts-1,params%field_sub_freq)==0) THEN
671        IF (ok_field2D_sub) CALL xios_send_field("field2D_sub",field2D*10)
672        IF (ok_field3D_sub) CALL xios_send_field("field3D_sub",field3D*10)
673      ENDIF
674
675      IF (ok_field3D_recv) THEN
676        IF (xios_field_is_active("field3D_resend",.TRUE.)) THEN
677          CALL xios_recv_field("field3D_recv",field3D_recv)
678          CALL xios_send_field("field3D_resend",field3D_recv)         
679         ENDIF
680      ENDIF
681
682! ensemble
683      IF (ok_field2D_W) CALL xios_send_field("field2D_W",field2D_W)
684      IF (ok_field3D_W) CALL xios_send_field("field3D_W",field3D_W)
685      IF (ok_pressure_W) CALL xios_send_field("pressure_W",pressure_W)
686      IF (ok_field_XW) CALL xios_send_field("field_XW",field_XW)
687      IF (ok_field_YW) CALL xios_send_field("field_YW",field_YW)
688      IF (ok_field_XYW) CALL xios_send_field("field_XYW",field_XYW)
689      IF (ok_field_ZW) CALL xios_send_field("field_ZW",field_ZW)
690      IF (ok_field_XYZW) CALL xios_send_field("field_XYZW",field_XYZW)
691      IF (ok_field_XZW) CALL xios_send_field("field_XZW",field_XZW)
692      IF (ok_field_YZW) CALL xios_send_field("field_YZW",field_YZW)
693      IF (ok_field0D_W) CALL xios_send_field("field0D_W",field0D_W)
694     
695      IF ( MOD(params%field_sub_offset+ts-1,params%field_sub_freq)==0) THEN
696        IF (ok_field2D_sub_W) CALL xios_send_field("field2D_sub_W",field2D_W*10)
697        IF (ok_field3D_sub_W) CALL xios_send_field("field3D_sub_W",field3D_W*10)
698      ENDIF
699
700      IF (ok_field3D_recv_W) THEN
701        IF (xios_field_is_active("field3D_resend_W",.TRUE.)) THEN
702          CALL xios_recv_field("field3D_recv_W",field3D_recv_W)
703          CALL xios_send_field("field3D_resend_W",field3D_recv_W)         
704         ENDIF
705      ENDIF
706
707      field2D=field2D+1
708      field3D=field3D+1
709      field0D=field0D+1
710
711!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
712!              duplicated section for other_                    !
713!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
714
715
716      IF (ok_other_field2D) CALL xios_send_field("other_field2D", other_field2D)
717      IF (ok_other_field3D) CALL xios_send_field("other_field3D", other_field3D)
718      IF (ok_other_pressure) CALL xios_send_field("other_pressure", other_pressure)
719      IF (ok_other_field_X) CALL xios_send_field("other_field_X", other_field_X)
720      IF (ok_other_field_Y) CALL xios_send_field("other_field_Y", other_field_Y)
721      IF (ok_other_field_XY) CALL xios_send_field("other_field_XY", other_field_XY)
722      IF (ok_other_field_Z) CALL xios_send_field("other_field_Z", other_field_Z)
723      IF (ok_other_field_XY) CALL xios_send_field("other_field_XYZ", other_field_XYZ)
724      IF (ok_other_field_XY) CALL xios_send_field("other_field_XZ", other_field_XZ)
725      IF (ok_other_field_XY) CALL xios_send_field("other_field_YZ", other_field_YZ)
726      IF (ok_other_field0D)  CALL xios_send_field("other_field0D", other_field0D)
727     
728      IF ( MOD(other_params%field_sub_offset+ts-1,other_params%field_sub_freq)==0) THEN
729        IF (ok_other_field2D_sub) CALL xios_send_field("other_field2D_sub",other_field2D*10)
730        IF (ok_other_field3D_sub) CALL xios_send_field("other_field3D_sub",other_field3D*10)
731      ENDIF
732
733      IF (ok_other_field3D_recv) THEN
734        IF (xios_field_is_active("other_field3D_resend",.TRUE.)) THEN
735          CALL xios_recv_field("other_field3D_recv",other_field3D_recv)
736          CALL xios_send_field("other_field3D_resend",other_field3D_recv)         
737         ENDIF
738      ENDIF
739
740! ensemble
741      IF (ok_other_field2D_W) CALL xios_send_field("other_field2D_W",other_field2D_W)
742      IF (ok_other_field3D_W) CALL xios_send_field("other_field3D_W",other_field3D_W)
743      IF (ok_other_pressure_W) CALL xios_send_field("other_pressure_W",other_pressure_W)
744      IF (ok_other_field_XW)  CALL xios_send_field("other_field_XW",other_field_XW)
745      IF (ok_other_field_YW)  CALL xios_send_field("other_field_YW",other_field_YW)
746      IF (ok_other_field_XYW) CALL xios_send_field("other_field_XYW",other_field_XYW)
747      IF (ok_other_field_ZW)  CALL xios_send_field("other_field_ZW",other_field_ZW)
748      IF (ok_other_field_XYW) CALL xios_send_field("other_field_XYZW",other_field_XYZW)
749      IF (ok_other_field_XYW) CALL xios_send_field("other_field_XZW",other_field_XZW)
750      IF (ok_other_field_XYW) CALL xios_send_field("other_field_YZW",other_field_YZW)
751      IF (ok_other_field0D_W)   CALL xios_send_field("other_field0D_W",other_field0D_W)
752     
753      IF ( MOD(other_params%field_sub_offset+ts-1,other_params%field_sub_freq)==0) THEN
754        IF (ok_other_field2D_sub_W) CALL xios_send_field("other_field2D_sub_W",other_field2D_W*10)
755        IF (ok_other_field3D_sub_W) CALL xios_send_field("other_field3D_sub_W",other_field3D_W*10)
756      ENDIF
757
758      IF (ok_other_field3D_recv_W) THEN
759        IF (xios_field_is_active("other_field3D_resend_W",.TRUE.)) THEN
760          CALL xios_recv_field("other_field3D_recv_W",other_field3D_recv_W)
761          CALL xios_send_field("other_field3D_resend_W",other_field3D_recv_W)         
762         ENDIF
763      ENDIF
764
765      other_field2D=other_field2D+1
766      other_field3D=other_field3D+1
767      other_field0D=other_field0D+1
768
769
770!!!!!!!!!!!!!!!!!!!!!! end of duplicated section !!!!!!!!!!!!!!!!!
771
772
773
774      !! Boucle d'attente
775      CALL wait_us(int(elapsed_per_timestep*1.e6))   ! micro-secondes
776      cdate=cdate+dtime
777      ts=ts+1
778    ENDDO
779   
780    CALL wait_us(int(10*1.e6))   ! micro-secondes
781    CALL xios_context_finalize()
782    CALL MPI_COMM_FREE(comm, ierr)
783   
784  END SUBROUTINE model
785
786  SUBROUTINE init_model_params(prefix,params)
787  IMPLICIT NONE
788    CHARACTER(LEN=*) :: prefix
789    TYPE(tmodel_params) :: params
790
791
792    IF (.NOT. xios_getvar(prefix//"timestep", params%timestep) )         params%timestep="1h"
793    IF (.NOT. xios_getvar(prefix//"domain", params%domain) )             params%domain="lmdz"
794    IF (.NOT. xios_getvar(prefix//"domain_mask", params%domain_mask) )   params%domain_mask=.FALSE.
795    IF (.NOT. xios_getvar(prefix//"domain_mask_type", params%domain_mask_type) )   params%domain_mask_type="cross"
796    IF (.NOT. xios_getvar(prefix//"scalar_mask", params%scalar_mask) )   params%scalar_mask=.FALSE.
797    IF (.NOT. xios_getvar(prefix//"scalar_mask_type", params%scalar_mask_type) )   params%scalar_mask_type="none"
798    IF (.NOT. xios_getvar(prefix//"axis", params%axis) )                 params%axis="pressure"
799    IF (.NOT. xios_getvar(prefix//"axis_mask", params%axis_mask) )       params%axis_mask=.FALSE.
800    IF (.NOT. xios_getvar(prefix//"ni", params%ni) )                     params%ni=36
801    IF (.NOT. xios_getvar(prefix//"nj", params%nj) )                     params%nj=18
802    IF (.NOT. xios_getvar(prefix//"nlev", params%nlev) )                 params%nlev=10
803    IF (.NOT. xios_getvar(prefix//"init_field2D", params%init_field2D) ) params%init_field2D="academic"
804    IF (.NOT. xios_getvar(prefix//"pressure_factor", params%pressure_factor) ) params%pressure_factor=0.
805    IF (.NOT. xios_getvar(prefix//"mask3d", params%mask3d) ) params%mask3d=.FALSE.
806    IF (.NOT. xios_getvar(prefix//"field_sub_freq", params%field_sub_freq) ) params%field_sub_freq=1
807    IF (.NOT. xios_getvar(prefix//"field_sub_offset", params%field_sub_offset) ) params%field_sub_offset=0
808
809    IF (.NOT. xios_getvar(prefix//"domain_proc_n", params%domain_proc_n)) params%domain_proc_n=0
810    IF (.NOT. xios_getvar(prefix//"axis_proc_n", params%axis_proc_n)) params%axis_proc_n=0
811    IF (.NOT. xios_getvar(prefix//"ensemble_proc_n", params%ensemble_proc_n)) params%ensemble_proc_n=1
812    IF ((.NOT. xios_getvar(prefix//"domain_proc_frac", params%domain_proc_frac)) .AND.  &
813       (.NOT. xios_getvar("prefix//axis_proc_frac", params%axis_proc_frac))) THEN
814       params%domain_proc_frac=1.0
815       params%axis_proc_frac=0.0
816    ELSE IF (.NOT. xios_getvar(prefix//"domain_proc_frac", params%domain_proc_frac)) THEN
817      params%domain_proc_frac=0.0
818    ELSE IF (.NOT. xios_getvar(prefix//"axis_proc_frac", params%axis_proc_frac)) THEN
819      params%axis_proc_frac=0.0
820    ENDIF
821   
822  END SUBROUTINE init_model_params
823
824 
825  SUBROUTINE init_domain(domain_id, comm, params, return_ni, return_nj,             &
826                         return_lon, return_lat, return_mask, return_index,         &
827                         return_X_lon,return_X_lat, return_X_mask, return_X_index,  &
828                         return_Y_lon,return_Y_lat, return_Y_mask, return_Y_index)
829  IMPLICIT NONE
830    CHARACTER(LEN=*),INTENT(IN) :: domain_id
831    TYPE(tmodel_params),INTENT(IN) :: params
832    INTEGER,INTENT(IN) :: comm
833    INTEGER,INTENT(OUT) :: return_ni
834    INTEGER,INTENT(OUT) :: return_nj
835    DOUBLE PRECISION, POINTER :: return_lon(:)
836    DOUBLE PRECISION, POINTER :: return_lat(:)
837    LOGICAL, POINTER :: return_mask(:)
838    INTEGER, POINTER :: return_index(:)
839    DOUBLE PRECISION, POINTER :: return_X_lon(:)
840    DOUBLE PRECISION, POINTER :: return_X_lat(:)
841    LOGICAL, POINTER :: return_X_mask(:)
842    INTEGER, POINTER :: return_X_index(:)
843    DOUBLE PRECISION, POINTER :: return_Y_lon(:)
844    DOUBLE PRECISION, POINTER :: return_Y_lat(:)
845    LOGICAL, POINTER :: return_Y_mask(:)
846    INTEGER, POINTER :: return_Y_index(:)
847       
848    IF (params%domain=="lmdz") THEN
849      CALL init_domain_lmdz(domain_id,comm,params, return_ni, return_nj,               &
850                            return_lon, return_lat, return_mask, return_index,         &
851                            return_X_lon,return_X_lat, return_X_mask, return_X_index,  &
852                            return_Y_lon,return_Y_lat, return_Y_mask, return_Y_index)
853
854    ELSE IF (params%domain=="orchidee") THEN
855     CALL init_domain_orchidee(domain_id,comm,params, return_ni, return_nj,               &
856                               return_lon, return_lat, return_mask, return_index,         &
857                               return_X_lon,return_X_lat, return_X_mask, return_X_index,  &
858                               return_Y_lon,return_Y_lat, return_Y_mask, return_Y_index)
859
860    ELSE IF (params%domain=="nemo") THEN
861       CALL init_domain_nemo(domain_id,comm,params, return_ni, return_nj,               &
862                             return_lon, return_lat, return_mask, return_index,         &
863                             return_X_lon,return_X_lat, return_X_mask, return_X_index,  &
864                             return_Y_lon,return_Y_lat, return_Y_mask, return_Y_index)
865
866     ELSE IF (params%domain=="dynamico") THEN
867       CALL init_domain_dynamico(domain_id,comm,params, return_ni, return_nj,               &
868                                 return_lon, return_lat, return_mask, return_index,         &
869                                 return_X_lon,return_X_lat, return_X_mask, return_X_index,  &
870                                 return_Y_lon,return_Y_lat, return_Y_mask, return_Y_index)
871
872     ELSE IF (params%domain=="gaussian") THEN
873       CALL init_domain_gaussian(domain_id,comm,params, return_ni, return_nj,               &
874                                 return_lon, return_lat, return_mask, return_index,         &
875                                 return_X_lon,return_X_lat, return_X_mask, return_X_index,  &
876                                 return_Y_lon,return_Y_lat, return_Y_mask, return_Y_index)
877    ENDIF
878   
879  END SUBROUTINE init_domain
880
881  SUBROUTINE init_field2D(comm,params, lon, lat, mask, return_field,        &
882                                       x_lon, x_lat, x_mask, return_fieldx, &
883                                       y_lon, y_lat, y_mask, return_fieldy, return_fieldXY)
884  IMPLICIT NONE
885    TYPE(tmodel_params) :: params
886    TYPE(xios_context) :: ctx_hdl
887    INTEGER :: comm
888    DOUBLE PRECISION, POINTER :: lon(:)
889    DOUBLE PRECISION, POINTER :: lat(:)
890    LOGICAL, POINTER :: mask(:)
891    DOUBLE PRECISION, POINTER :: return_field(:)
892
893    DOUBLE PRECISION, POINTER :: X_lon(:)
894    DOUBLE PRECISION, POINTER :: X_lat(:)
895    LOGICAL, POINTER :: X_mask(:)
896    DOUBLE PRECISION, POINTER :: return_fieldX(:)
897
898    DOUBLE PRECISION, POINTER :: Y_lon(:)
899    DOUBLE PRECISION, POINTER :: Y_lat(:)
900    LOGICAL, POINTER :: Y_mask(:)
901    DOUBLE PRECISION, POINTER :: return_fieldY(:)
902    DOUBLE PRECISION, POINTER :: return_fieldXY(:,:)
903       
904    IF (params%init_field2D=="academic") THEN
905      CALL init_field2D_academic(comm,params, lon, lat, mask, return_field, X_lon, X_lat, X_mask, return_fieldX, &
906                                Y_lon, Y_lat, Y_mask, return_fieldY, return_fieldXY)
907    ELSE IF (params%init_field2D=="constant") THEN
908      CALL init_field2D_constant(comm,params, lon, lat, mask, return_field, X_lon, X_lat, X_mask, return_fieldX, &
909                                 Y_lon, Y_lat, Y_mask, return_fieldY, return_fieldXY)
910    ELSE IF (params%init_field2D=="rank") THEN
911      CALL init_field2D_rank(comm,params, lon, lat, mask, return_field, X_lon, X_lat, X_mask, &
912                             return_fieldX, Y_lon, Y_lat, Y_mask, return_fieldY, return_fieldXY)
913    ENDIF
914   
915  END SUBROUTINE init_field2D
916
917 
918  SUBROUTINE init_axis(axis_id,comm,params, return_value, return_mask, return_index)
919  IMPLICIT NONE
920    CHARACTER(LEN=*) :: axis_id
921    TYPE(tmodel_params) :: params
922    TYPE(xios_context) :: ctx_hdl
923    INTEGER :: comm
924    DOUBLE PRECISION, POINTER :: return_value(:)
925    LOGICAL, POINTER          :: return_mask(:)
926    INTEGER, POINTER          :: return_index(:)
927   
928    IF (params%axis=="pressure") THEN
929      CALL init_axis_pressure(axis_id,comm,params, return_value, return_mask, return_index)
930    ENDIF
931   
932   END SUBROUTINE init_axis
933   
934  SUBROUTINE init_ensemble(ensemble_id,comm,params, return_value)
935  IMPLICIT NONE
936    CHARACTER(LEN=*) :: ensemble_id
937    TYPE(tmodel_params) :: params
938    TYPE(xios_context) :: ctx_hdl
939    INTEGER :: comm
940    DOUBLE PRECISION, POINTER :: return_value(:)
941    INTEGER :: domain_proc_rank, domain_proc_size   
942    INTEGER :: axis_proc_rank, axis_proc_size
943    INTEGER :: ensemble_proc_size, ensemble_proc_rank
944
945    CALL get_decomposition(comm, params, domain_proc_size, domain_proc_rank, axis_proc_size, axis_proc_rank, ensemble_proc_size, ensemble_proc_rank)
946    ALLOCATE(return_value(0:0))
947    return_value(0)=ensemble_proc_rank
948
949    IF (xios_is_valid_axis(TRIM(ensemble_id))) THEN
950      CALL xios_set_axis_attr(ensemble_id, n_glo=ensemble_proc_size, begin=ensemble_proc_rank, n=1, value=return_value(:), unit='-')   
951    ENDIF
952   
953   END SUBROUTINE init_ensemble
954   
955
956  SUBROUTINE init_domain_gaussian(domain_id, comm, params, return_ni, return_nj,               &
957                                  return_lon,return_lat,return_mask, return_index,             &
958                                  return_X_lon,return_X_lat, return_X_mask, return_X_index,    &
959                                  return_Y_lon,return_Y_lat, return_Y_mask, return_Y_index)
960  IMPLICIT NONE
961    CHARACTER(LEN=*) :: domain_id
962    TYPE(tmodel_params) :: params
963    TYPE(xios_context) :: ctx_hdl
964    INTEGER :: comm
965    INTEGER :: return_ni
966    INTEGER :: return_nj
967    DOUBLE PRECISION, POINTER :: return_lon(:)
968    DOUBLE PRECISION, POINTER :: return_lat(:)
969    LOGICAL, POINTER :: return_mask(:)
970    INTEGER, POINTER :: return_index(:)
971    DOUBLE PRECISION, POINTER :: return_X_lon(:)
972    DOUBLE PRECISION, POINTER :: return_X_lat(:)
973    LOGICAL, POINTER :: return_X_mask(:)
974    INTEGER, POINTER :: return_X_index(:)
975    DOUBLE PRECISION, POINTER :: return_Y_lon(:)
976    DOUBLE PRECISION, POINTER :: return_Y_lat(:)
977    LOGICAL, POINTER :: return_Y_mask(:)
978    INTEGER, POINTER :: return_Y_index(:)
979    INTEGER :: domain_proc_rank, domain_proc_size   
980    INTEGER :: axis_proc_rank, axis_proc_size
981    INTEGER :: ensemble_proc_size, ensemble_proc_rank
982
983    INTEGER :: mpi_rank, mpi_size
984    INTEGER ::  ierr
985   
986!  INTEGER, PARAMETER :: nlon=60
987!  INTEGER, PARAMETER :: nlat=30
988!  INTEGER,PARAMETER :: ni_glo=100
989!  INTEGER,PARAMETER :: nj_glo=100
990!  INTEGER,PARAMETER :: llm=5
991!  DOUBLE PRECISION  :: lval(llm)=1
992!  TYPE(xios_field) :: field_hdl
993!  TYPE(xios_fieldgroup) :: fieldgroup_hdl
994!  TYPE(xios_file) :: file_hdl
995!  LOGICAL :: ok
996
997!  DOUBLE PRECISION,ALLOCATABLE :: lon_glo(:),lat_glo(:)
998!  DOUBLE PRECISION,ALLOCATABLE :: bounds_lon_glo(:,:),bounds_lat_glo(:,:)
999!  DOUBLE PRECISION,ALLOCATABLE :: field_A_glo(:,:)
1000!  INTEGER,ALLOCATABLE :: i_index_glo(:)
1001!  INTEGER,ALLOCATABLE :: i_index(:)
1002!  LOGICAL,ALLOCATABLE :: mask_glo(:),mask(:)
1003!  INTEGER,ALLOCATABLE :: n_local(:),local_neighbor(:,:)
1004!  DOUBLE PRECISION,ALLOCATABLE :: lon(:),lat(:),field_A_srf(:,:), lonvalue(:) ;
1005!  DOUBLE PRECISION,ALLOCATABLE :: bounds_lon(:,:),bounds_lat(:,:) ;
1006!  INTEGER :: ni,ibegin,iend,nj,jbegin,jend
1007!  INTEGER :: i,j,l,ts,n, nbMax
1008!  INTEGER :: ncell_glo,ncell,ind
1009!  REAL :: ilon,ilat
1010!  DOUBLE PRECISION, PARAMETER :: Pi=3.14159265359
1011!  INTEGER :: list_ind(nlon,nlat)
1012!  INTEGER :: rank,j1,j2,np,ncell_x
1013!  INTEGER :: data_n_index
1014!  INTEGER,ALLOCATABLE :: data_i_index(:)
1015!  DOUBLE PRECISION,ALLOCATABLE :: field_A_compressed(:,:)
1016
1017
1018    INTEGER :: nlon, nlat
1019    DOUBLE PRECISION,ALLOCATABLE :: lon_glo(:),lat_glo(:)
1020    DOUBLE PRECISION,ALLOCATABLE :: bounds_lon_glo(:,:),bounds_lat_glo(:,:)
1021    INTEGER,ALLOCATABLE :: i_index_glo(:)
1022    INTEGER,ALLOCATABLE :: i_index(:)
1023    LOGICAL,ALLOCATABLE :: mask_glo(:),mask(:)
1024    DOUBLE PRECISION,ALLOCATABLE :: lon(:),lat(:),field_A_srf(:,:), lonvalue(:) ;
1025    DOUBLE PRECISION,ALLOCATABLE :: bounds_lon(:,:),bounds_lat(:,:) ;
1026
1027    INTEGER :: ni,ibegin,iend,nj,jbegin,jend
1028    INTEGER :: i,j,l,ts,n, nbMax
1029    INTEGER :: ncell_glo,ncell,ind
1030    REAL :: ilon,ilat
1031    DOUBLE PRECISION, PARAMETER :: Pi=3.14159265359
1032    INTEGER,ALLOCATABLE :: list_ind(:,:)
1033    INTEGER :: rank,j1,j2,np,ncell_x
1034    INTEGER :: data_n_index
1035    INTEGER,ALLOCATABLE :: data_i_index(:)
1036
1037
1038
1039    CALL MPI_COMM_RANK(comm,mpi_rank,ierr)
1040    CALL MPI_COMM_SIZE(comm,mpi_size,ierr)
1041
1042    CALL get_decomposition(comm, params, domain_proc_size, domain_proc_rank, axis_proc_size, axis_proc_rank, ensemble_proc_size, ensemble_proc_rank)
1043
1044    mpi_rank=domain_proc_rank
1045    mpi_size=domain_proc_size
1046    nlon=params%ni
1047    nlat=params%nj
1048
1049   
1050    ncell_glo=0
1051    DO j=1,nlat
1052      n =  NINT(COS(Pi/2-(j-0.5)*PI/nlat)*nlon)
1053      IF (n<8) n=8
1054      ncell_glo=ncell_glo+n
1055    ENDDO
1056
1057    ALLOCATE(lon_glo(ncell_glo))
1058    ALLOCATE(lat_glo(ncell_glo))
1059    ALLOCATE(bounds_lon_glo(4,ncell_glo))
1060    ALLOCATE(bounds_lat_glo(4,ncell_glo))
1061    ALLOCATE(i_index_glo(ncell_glo))
1062    ALLOCATE(mask_glo(ncell_glo))
1063    ALLOCATE(list_ind(nlon,nlat))
1064   
1065    ind=0
1066    DO j=1,nlat
1067      n = NINT(COS(Pi/2-(j-0.5)*PI/nlat)*nlon)
1068      if (j==1) PRINT*,"--- ",n
1069      if (j==nlat) PRINT*,"--- ",n
1070      IF (n<8) n=8
1071
1072      DO i=1,n
1073        ind=ind+1
1074        list_ind(i,j)=ind
1075        ilon=i-0.5
1076        ilat=j-0.5
1077
1078        lat_glo(ind)= 90-(ilat*180./nlat)
1079        lon_glo(ind)= (ilon*360./n)-180.
1080
1081
1082        bounds_lat_glo(1,ind)= 90-((ilat-0.5)*180./nlat)
1083        bounds_lon_glo(1,ind)=((ilon-0.5)*360./n)-180.
1084
1085        bounds_lat_glo(2,ind)= 90-((ilat-0.5)*180./nlat)
1086        bounds_lon_glo(2,ind)=((ilon+0.5)*360./n)-180.
1087
1088        bounds_lat_glo(3,ind)= 90-((ilat+0.5)*180./nlat)
1089        bounds_lon_glo(3,ind)=((ilon+0.5)*360./n)-180.
1090
1091        bounds_lat_glo(4,ind)= 90-((ilat+0.5)*180./nlat)
1092        bounds_lon_glo(4,ind)=((ilon-0.5)*360./n)-180.
1093
1094      ENDDO
1095    ENDDO
1096
1097!  mpi_size=32
1098    rank=(mpi_size-1)/2
1099    ncell_x=sqrt(ncell_glo*1./mpi_size)
1100
1101    j1=nlat/2
1102    DO WHILE(rank>=0)
1103      j2=MAX(j1-ncell_x+1,1)
1104      j=(j1+j2)/2
1105      n=NINT(COS(Pi/2-(j-0.5)*PI/nlat)*nlon)
1106      np = MIN(n/ncell_x,rank+1) ;
1107      if (j2==1) np=rank+1
1108 
1109      PRINT *,"domain ",j2,j1,rank,np ;
1110      DO j=j2,j1
1111        n=NINT(COS(Pi/2-(j-0.5)*PI/nlat)*nlon)
1112        IF (n<8) n=8
1113        DO i=1,n
1114          ind=list_ind(i,j)
1115          IF ( (i-1) < MOD(n,np)*(n/np+1)) THEN 
1116            i_index_glo(ind) = rank - (i-1)/(n/np+1)
1117          ELSE
1118            i_index_glo(ind) = rank-(MOD(n,np)+ (i-1-MOD(n,np)*(n/np+1))/(n/np))
1119          ENDIF
1120        ENDDO
1121      ENDDO
1122      rank=rank-np
1123      j1=j2-1
1124    ENDDO
1125
1126    rank=(mpi_size-1)/2+1
1127    ncell_x=sqrt(ncell_glo*1./mpi_size)
1128
1129    j1=nlat/2+1
1130    DO WHILE(rank<=mpi_size-1)
1131      j2=MIN(j1+ncell_x-1,nlat)
1132      j=(j1+j2)/2
1133      n=NINT(COS(Pi/2-(j-0.5)*PI/nlat)*nlon)
1134      np = MIN(n/ncell_x,mpi_size-rank) ;
1135      if (j2==nlat) np=mpi_size-rank
1136
1137      PRINT *,"domain ",j2,j1,rank,np ;
1138      DO j=j1,j2
1139        n=NINT(COS(Pi/2-(j-0.5)*PI/nlat)*nlon)
1140        IF (n<8) n=8
1141        DO i=1,n
1142          ind=list_ind(i,j)
1143          IF ( (i-1) < MOD(n,np)*(n/np+1)) THEN
1144            i_index_glo(ind) = rank + (i-1)/(n/np+1)
1145          ELSE
1146            i_index_glo(ind) = rank+(MOD(n,np)+ (i-1-MOD(n,np)*(n/np+1))/(n/np))
1147          ENDIF
1148        ENDDO
1149      ENDDO
1150      rank=rank+np
1151      j1=j2+1
1152   ENDDO
1153
1154    ncell=0
1155    DO ind=1,ncell_glo
1156      IF (i_index_glo(ind)==mpi_rank) ncell=ncell+1
1157    ENDDO
1158    ALLOCATE(i_index(ncell))
1159    ALLOCATE(lon(ncell))
1160    ALLOCATE(lat(ncell))
1161    ALLOCATE(bounds_lon(4,ncell))
1162    ALLOCATE(bounds_lat(4,ncell))
1163!    ALLOCATE(field_A_srf(ncell,llm))
1164    ALLOCATE(mask(ncell))
1165    ncell=0
1166    data_n_index=0
1167    DO ind=1,ncell_glo
1168      IF (i_index_glo(ind)==mpi_rank) THEN
1169        ncell=ncell+1
1170        i_index(ncell)=ind-1
1171        lon(ncell)=lon_glo(ind)
1172        lat(ncell)=lat_glo(ind)
1173        bounds_lon(:,ncell)=bounds_lon_glo(:,ind)
1174        bounds_lat(:,ncell)=bounds_lat_glo(:,ind)
1175        field_A_srf(ncell,:)=i_index_glo(ind)
1176        IF (MOD(ind,8)>=0 .AND. MOD(ind,8)<2) THEN
1177!        mask(ncell)=.FALSE.
1178
1179         mask(ncell)=.TRUE.
1180          data_n_index=data_n_index+1
1181        ELSE
1182          mask(ncell)=.TRUE.
1183          data_n_index=data_n_index+1
1184        ENDIF
1185      ENDIF
1186    ENDDO
1187
1188!    ALLOCATE(field_A_compressed(data_n_index,llm))
1189    ALLOCATE(data_i_index(data_n_index))
1190    data_n_index=0
1191    DO ind=1,ncell
1192      IF (mask(ind)) THEN
1193        data_n_index=data_n_index+1
1194        data_i_index(data_n_index)=ind-1
1195!        field_A_compressed(data_n_index,:)=field_A_srf(ind,:)
1196      ENDIF
1197    ENDDO
1198
1199    ALLOCATE(return_lon(0:ncell-1))
1200    ALLOCATE(return_lat(0:ncell-1))
1201    ALLOCATE(return_mask(0:ncell-1))
1202    ALLOCATE(return_index(0:data_n_index-1))
1203    return_lon(0:ncell-1)=lon(1:ncell)   
1204    return_lat(0:ncell-1)=lat(1:ncell)
1205    return_index(0:data_n_index-1)= data_i_index(1:data_n_index) 
1206    CALL set_domain_mask(params, lon, lat, return_mask)
1207
1208
1209    ALLOCATE(return_X_lon(0:ncell-1))
1210    ALLOCATE(return_X_lat(0:ncell-1))
1211    ALLOCATE(return_X_mask(0:ncell-1))
1212    ALLOCATE(return_X_index(0:ncell-1))
1213   
1214    return_X_lon=return_lon
1215    return_X_lat=return_lat
1216    return_X_index=return_index
1217    CALL set_domain_mask(params, return_X_lon,return_X_lat, return_X_mask)
1218
1219
1220    ALLOCATE(return_Y_lon(0:0))
1221    ALLOCATE(return_Y_lat(0:0))
1222    ALLOCATE(return_Y_mask(0:0))
1223    ALLOCATE(return_Y_index(0:0))
1224
1225    return_Y_lon(0)=lon_glo(ncell_glo/2)
1226    return_Y_lat(0)=lat_glo(ncell_glo/2)
1227    CALL set_domain_mask(params, return_Y_lon,return_Y_lat, return_Y_mask)
1228    return_Y_index(0)=0
1229
1230    return_ni=ncell
1231    return_nj=1
1232
1233
1234    IF (xios_is_valid_domain(TRIM(domain_id))) THEN
1235      CALL xios_set_domain_attr(TRIM(domain_id), type="unstructured", ni_glo=ncell_glo, ni=ncell, ibegin=0, i_index=i_index)
1236      CALL xios_set_domain_attr(TRIM(domain_id), data_dim=1, data_ni=data_n_index, data_i_index=data_i_index, mask_1d=return_mask)
1237      CALL xios_set_domain_attr(TRIM(domain_id), lonvalue_1D=lon, latvalue_1D=lat, nvertex=4, bounds_lon_1D=bounds_lon, bounds_lat_1D=bounds_lat)
1238    ENDIF
1239
1240    IF (xios_is_valid_axis(TRIM(domain_id)//"_X")) THEN
1241      CALL xios_set_axis_attr(TRIM(domain_id)//"_X", n_glo=ncell_glo, n=ncell, begin=0, index=i_index,value=return_X_lon)
1242      CALL xios_set_axis_attr(TRIM(domain_id)//"_X", data_n=data_n_index, data_index=data_i_index, mask=return_X_mask)
1243    ENDIF
1244   
1245    IF (xios_is_valid_axis(TRIM(domain_id)//"_Y")) THEN   
1246      CALL xios_set_axis_attr(TRIM(domain_id)//"_Y", n_glo=1, begin=0, n=1, value=return_Y_lat, mask=return_Y_mask)
1247    ENDIF
1248
1249
1250
1251  END SUBROUTINE init_domain_gaussian
1252
1253
1254
1255  SUBROUTINE init_domain_dynamico(domain_id, comm, params, return_ni, return_nj,               &
1256                              return_lon,return_lat,return_mask, return_index,             &
1257                              return_X_lon,return_X_lat, return_X_mask, return_X_index,    &
1258                              return_Y_lon,return_Y_lat, return_Y_mask, return_Y_index)
1259  IMPLICIT NONE
1260    CHARACTER(LEN=*) :: domain_id
1261    TYPE(tmodel_params) :: params
1262    TYPE(xios_context) :: ctx_hdl
1263    INTEGER :: comm
1264    INTEGER :: return_ni
1265    INTEGER :: return_nj
1266    DOUBLE PRECISION, POINTER :: return_lon(:)
1267    DOUBLE PRECISION, POINTER :: return_lat(:)
1268    LOGICAL, POINTER :: return_mask(:)
1269    INTEGER, POINTER :: return_index(:)
1270    DOUBLE PRECISION, POINTER :: return_X_lon(:)
1271    DOUBLE PRECISION, POINTER :: return_X_lat(:)
1272    LOGICAL, POINTER :: return_X_mask(:)
1273    INTEGER, POINTER :: return_X_index(:)
1274    DOUBLE PRECISION, POINTER :: return_Y_lon(:)
1275    DOUBLE PRECISION, POINTER :: return_Y_lat(:)
1276    LOGICAL, POINTER :: return_Y_mask(:)
1277    INTEGER, POINTER :: return_Y_index(:)
1278    INTEGER :: domain_proc_rank, domain_proc_size   
1279    INTEGER :: axis_proc_rank, axis_proc_size
1280    INTEGER :: ensemble_proc_size, ensemble_proc_rank
1281
1282    INTEGER :: mpi_rank, mpi_size
1283    INTEGER ::  ierr
1284    INTEGER :: ni,nj,ni_glo,nj_glo,nvertex
1285    INTEGER :: ibegin,jbegin
1286    INTEGER :: nbp,nbp_glo, offset
1287    DOUBLE PRECISION, ALLOCATABLE :: lon_glo(:), lat_glo(:), lon(:), lat(:)
1288    DOUBLE PRECISION, ALLOCATABLE :: bounds_lon_glo(:,:), bounds_lat_glo(:,:), bounds_lon(:,:), bounds_lat(:,:)
1289    LOGICAL,ALLOCATABLE :: mask(:)
1290    LOGICAL,ALLOCATABLE :: dom_mask(:)
1291    INTEGER :: i,j
1292    INTEGER,ALLOCATABLE :: ibegin_all(:), ni_all(:)
1293       
1294    CALL MPI_COMM_RANK(comm,mpi_rank,ierr)
1295    CALL MPI_COMM_SIZE(comm,mpi_size,ierr)
1296
1297    CALL get_decomposition(comm, params, domain_proc_size, domain_proc_rank, axis_proc_size, axis_proc_rank, ensemble_proc_size, ensemble_proc_rank)
1298
1299    CALL xios_get_current_context(ctx_hdl)
1300   
1301    CALL xios_context_initialize("grid_dynamico",comm)
1302    CALL xios_close_context_definition()
1303    CALL xios_get_domain_attr("Ai::",ni_glo=ni_glo,nj_glo=nj_glo,ni=ni,nj=nj, ibegin=ibegin, jbegin=jbegin ,nvertex=nvertex)
1304    ALLOCATE(lon(ni),lat(ni),bounds_lon(nvertex,ni),bounds_lat(nvertex,ni))
1305    CALL xios_get_domain_attr("Ai::", lonvalue_1d=lon, latvalue_1d=lat, bounds_lon_1d=bounds_lon, bounds_lat_1d=bounds_lat)
1306    CALL xios_context_finalize
1307
1308    CALL xios_set_current_context(ctx_hdl)
1309
1310   
1311    ALLOCATE(ibegin_all(mpi_size))
1312    ALLOCATE(ni_all(mpi_size))
1313    ALLOCATE(lon_glo(0:ni_glo-1))
1314    ALLOCATE(lat_glo(0:ni_glo-1))
1315    ALLOCATE(bounds_lon_glo(nvertex,0:ni_glo-1))
1316    ALLOCATE(bounds_lat_glo(nvertex,0:ni_glo-1))
1317   
1318    CALL MPI_Allgather(ibegin, 1, MPI_INTEGER, ibegin_all, 1, MPI_INTEGER, comm, ierr)
1319    CALL MPI_Allgather(ni, 1, MPI_INTEGER, ni_all, 1, MPI_INTEGER, comm, ierr)
1320
1321    CALL MPI_AllgatherV(lon, ni, MPI_REAL8, lon_glo, ni_all, ibegin_all, MPI_REAL8, comm, ierr) 
1322    CALL MPI_AllgatherV(lat, ni, MPI_REAL8, lat_glo, ni_all, ibegin_all, MPI_REAL8, comm, ierr) 
1323    CALL MPI_AllgatherV(bounds_lon, ni*nvertex, MPI_REAL8, bounds_lon_glo, ni_all*nvertex, ibegin_all*nvertex, MPI_REAL8, comm, ierr) 
1324    CALL MPI_AllgatherV(bounds_lat, ni*nvertex, MPI_REAL8, bounds_lat_glo, ni_all*nvertex, ibegin_all*nvertex, MPI_REAL8, comm, ierr) 
1325
1326   
1327    nbp_glo=ni_glo
1328    nbp=nbp_glo/domain_proc_size
1329    IF (domain_proc_rank < MOD(nbp_glo,domain_proc_size) ) THEN
1330      nbp=nbp+1
1331      offset=nbp*domain_proc_rank
1332    ELSE
1333      offset=nbp*domain_proc_rank + MOD(nbp_glo, domain_proc_size)
1334    ENDIF
1335
1336    DEALLOCATE(lat,lon,bounds_lon,bounds_lat)
1337    ALLOCATE(lat(0:nbp-1))
1338    ALLOCATE(lon(0:nbp-1))
1339    ALLOCATE(bounds_lon(nvertex,0:nbp-1))
1340    ALLOCATE(bounds_lat(nvertex,0:nbp-1))
1341    ALLOCATE(return_lon(0:nbp-1))
1342    ALLOCATE(return_lat(0:nbp-1))
1343    ALLOCATE(return_index(0:nbp-1))
1344
1345    DO i=0,nbp-1
1346      lat(i)=lat_glo(i+offset)
1347      lon(i)=lon_glo(i+offset)
1348      bounds_lon(:,i) = bounds_lon_glo(:,i+offset) 
1349      bounds_lat(:,i) = bounds_lat_glo(:,i+offset)
1350      return_index(i)=i 
1351    ENDDO
1352    return_lon=lon
1353    return_lat=lat
1354   
1355    ALLOCATE(return_mask(0:nbp-1))
1356    CALL set_domain_mask(params, lon, lat, return_mask)
1357
1358
1359    ALLOCATE(return_X_lon(0:nbp-1))
1360    ALLOCATE(return_X_lat(0:nbp-1))
1361    ALLOCATE(return_X_mask(0:nbp-1))
1362    ALLOCATE(return_X_index(0:nbp-1))
1363   
1364    DO i=0,nbp-1
1365      return_X_lon(i)=lon_glo(i+offset)
1366      return_X_lat(i)=lat_glo(i+offset)
1367    ENDDO
1368    CALL set_domain_mask(params, return_X_lon,return_X_lat, return_X_mask)
1369    DO i=0,nbp-1
1370      return_X_index(i)=i
1371    ENDDO
1372
1373    ALLOCATE(return_Y_lon(0:0))
1374    ALLOCATE(return_Y_lat(0:0))
1375    ALLOCATE(return_Y_mask(0:0))
1376    ALLOCATE(return_Y_index(0:0))
1377
1378    return_Y_lon(0)=lon_glo(nbp_glo/2)
1379    return_Y_lat(0)=lat_glo(nbp_glo/2)
1380    CALL set_domain_mask(params, return_Y_lon,return_Y_lat, return_Y_mask)
1381    return_Y_index(0)=0
1382 
1383
1384   
1385    return_ni=nbp
1386    return_nj=1
1387
1388    IF (xios_is_valid_domain(TRIM(domain_id))) THEN
1389      CALL xios_set_domain_attr(TRIM(domain_id), type="unstructured", ni_glo=ni_glo, ibegin=offset, ni=nbp, nvertex=nvertex)
1390      CALL xios_set_domain_attr(TRIM(domain_id), data_dim=1, lonvalue_1d=lon, latvalue_1d=lat, bounds_lon_1d=bounds_lon, bounds_lat_1d=bounds_lat, mask_1d=return_mask)
1391    ENDIF   
1392
1393    IF (xios_is_valid_axis(TRIM(domain_id)//"_X")) THEN
1394      CALL xios_set_axis_attr(TRIM(domain_id)//"_X", n_glo=ni_glo, begin=offset, n=nbp, value=return_X_lon)
1395    ENDIF
1396
1397    IF (xios_is_valid_axis(TRIM(domain_id)//"_Y")) THEN   
1398      CALL xios_set_axis_attr(TRIM(domain_id)//"_Y", n_glo=1, begin=0, n=1, value=return_Y_lat, mask=return_Y_mask)
1399    ENDIF
1400
1401   END SUBROUTINE init_domain_dynamico
1402   
1403
1404
1405
1406  SUBROUTINE init_domain_lmdz(domain_id, comm, params, return_ni, return_nj,               &
1407                              return_lon,return_lat,return_mask, return_index,             &
1408                              return_X_lon,return_X_lat, return_X_mask, return_X_index,    &
1409                              return_Y_lon,return_Y_lat, return_Y_mask, return_Y_index)
1410  IMPLICIT NONE
1411    CHARACTER(LEN=*) :: domain_id
1412    TYPE(tmodel_params) :: params
1413    TYPE(xios_context) :: ctx_hdl
1414    INTEGER :: comm
1415    INTEGER :: return_ni
1416    INTEGER :: return_nj
1417    DOUBLE PRECISION, POINTER :: return_lon(:)
1418    DOUBLE PRECISION, POINTER :: return_lat(:)
1419    LOGICAL, POINTER :: return_mask(:)
1420    INTEGER, POINTER :: return_index(:)
1421    DOUBLE PRECISION, POINTER :: return_X_lon(:)
1422    DOUBLE PRECISION, POINTER :: return_X_lat(:)
1423    LOGICAL, POINTER :: return_X_mask(:)
1424    INTEGER, POINTER :: return_X_index(:)
1425    DOUBLE PRECISION, POINTER :: return_Y_lon(:)
1426    DOUBLE PRECISION, POINTER :: return_Y_lat(:)
1427    LOGICAL, POINTER :: return_Y_mask(:)
1428    INTEGER, POINTER :: return_Y_index(:)
1429    INTEGER :: domain_proc_rank, domain_proc_size   
1430    INTEGER :: axis_proc_rank, axis_proc_size
1431    INTEGER :: ensemble_proc_size, ensemble_proc_rank
1432
1433    INTEGER :: mpi_rank, mpi_size
1434    INTEGER ::  ierr
1435    INTEGER :: ni,nj,ni_glo,nj_glo
1436    INTEGER :: ibegin,jbegin
1437    INTEGER :: nbp,nbp_glo, offset
1438    DOUBLE PRECISION, ALLOCATABLE :: lon_glo(:), lat_glo(:), lon(:), lat(:)
1439    LOGICAL,ALLOCATABLE :: mask(:)
1440    LOGICAL,ALLOCATABLE :: dom_mask(:)
1441    INTEGER :: i,j
1442       
1443    CALL MPI_COMM_RANK(comm,mpi_rank,ierr)
1444    CALL MPI_COMM_SIZE(comm,mpi_size,ierr)
1445
1446    CALL get_decomposition(comm, params, domain_proc_size, domain_proc_rank, axis_proc_size, axis_proc_rank, ensemble_proc_size, ensemble_proc_rank)
1447    ni_glo=params%ni
1448    nj_glo=params%nj
1449    nbp_glo=ni_glo*nj_glo
1450    nbp=nbp_glo/domain_proc_size
1451    IF (domain_proc_rank < MOD(nbp_glo,domain_proc_size) ) THEN
1452     nbp=nbp+1
1453     offset=nbp*domain_proc_rank
1454    ELSE
1455      offset=nbp*domain_proc_rank + MOD(nbp_glo, domain_proc_size)
1456    ENDIF
1457   
1458   
1459    ibegin=0 ; ni=ni_glo
1460    jbegin=offset / ni_glo
1461   
1462    nj = (offset+nbp-1) / ni_glo - jbegin + 1 
1463   
1464    offset=offset-jbegin*ni
1465   
1466    ALLOCATE(lon(0:ni-1), lat(0:nj-1), mask(0:ni*nj-1), dom_mask(0:ni*nj-1))
1467    mask(:)=.FALSE.
1468    mask(offset:offset+nbp-1)=.TRUE.
1469   
1470    ALLOCATE(lon_glo(0:ni_glo-1), lat_glo(0:nj_glo-1))
1471   
1472    DO i=0,ni_glo-1
1473      lon_glo(i)=-180+(i+0.5)*(360./ni_glo)
1474    ENDDO
1475
1476    DO j=0,nj_glo-1
1477      lat_glo(j)=-90+(j+0.5)*(180./nj_glo)
1478    ENDDO
1479     
1480    lon(:)=lon_glo(:)
1481    lat(:)=lat_glo(jbegin:jbegin+nj-1)
1482
1483    ALLOCATE(return_lon(0:ni*nj-1))
1484    ALLOCATE(return_lat(0:ni*nj-1))
1485    ALLOCATE(return_mask(0:ni*nj-1))
1486    ALLOCATE(return_index(0:ni*nj-1))
1487
1488    ALLOCATE(return_X_lon(0:ni-1))
1489    ALLOCATE(return_X_lat(0:ni-1))
1490    ALLOCATE(return_X_mask(0:ni-1))
1491    ALLOCATE(return_X_index(0:ni-1))
1492
1493    ALLOCATE(return_Y_lon(0:nj-1))
1494    ALLOCATE(return_Y_lat(0:nj-1))
1495    ALLOCATE(return_Y_mask(0:nj-1))
1496    ALLOCATE(return_Y_index(0:nj-1))
1497
1498    DO j=0,nj-1
1499      DO i=0,ni-1
1500        return_lon(i+j*ni)=lon(i)
1501        return_lat(i+j*ni)=lat(j)
1502        return_index(i+j*ni)=i+j*ni
1503      ENDDO
1504    ENDDO
1505
1506    CALL set_domain_mask(params, return_lon,return_lat, dom_mask)
1507   
1508    return_mask = mask .AND. dom_mask
1509
1510    return_X_lat(:)=lat_glo(nj_glo/2)
1511    return_X_lon(:)=lon_glo(:)
1512    CALL set_domain_mask(params, return_X_lon,return_X_lat, return_X_mask)
1513    DO i=0,ni-1
1514      return_X_index(i)=i
1515    ENDDO
1516
1517    return_Y_lon(:)=lon_glo(ni_glo/2)
1518    return_Y_lat(:)=lat_glo(jbegin:jbegin+nj-1)
1519    CALL set_domain_mask(params, return_Y_lon,return_Y_lat, return_Y_mask)
1520
1521    DO j=0,nj-1
1522      return_Y_index(j)=j
1523    ENDDO
1524
1525    return_ni=ni
1526    return_nj=nj
1527
1528    IF (xios_is_valid_domain(TRIM(domain_id))) THEN
1529      CALL xios_set_domain_attr(TRIM(domain_id), type="rectilinear", ni_glo=ni_glo, ibegin=ibegin, ni=ni, nj_glo=nj_glo, jbegin=jbegin, nj=nj)
1530      CALL xios_set_domain_attr(TRIM(domain_id), data_dim=2, lonvalue_1d=lon, latvalue_1d=lat, mask_1d=return_mask)
1531    ENDIF
1532   
1533    IF (xios_is_valid_axis(TRIM(domain_id)//"_X")) THEN
1534      CALL xios_set_axis_attr(TRIM(domain_id)//"_X", n_glo=ni_glo, begin=ibegin, n=ni, value=return_X_lon, mask=return_X_mask)
1535    ENDIF
1536
1537    IF (xios_is_valid_axis(TRIM(domain_id)//"_Y")) THEN   
1538      CALL xios_set_axis_attr(TRIM(domain_id)//"_Y", n_glo=nj_glo, begin=jbegin, n=nj, value=return_Y_lat, mask=return_Y_mask)
1539    ENDIF
1540
1541  END SUBROUTINE init_domain_lmdz
1542
1543
1544  SUBROUTINE init_domain_orchidee(domain_id, comm, params, return_ni, return_nj,               &
1545                                  return_lon,return_lat,return_mask, return_index,             &
1546                                  return_X_lon,return_X_lat, return_X_mask, return_X_index,    &
1547                                  return_Y_lon,return_Y_lat, return_Y_mask, return_Y_index)
1548  IMPLICIT NONE
1549    CHARACTER(LEN=*) :: domain_id
1550    TYPE(tmodel_params) :: params
1551    TYPE(xios_context) :: ctx_hdl
1552    INTEGER :: comm
1553    INTEGER :: return_ni
1554    INTEGER :: return_nj
1555    DOUBLE PRECISION, POINTER :: return_lon(:)
1556    DOUBLE PRECISION, POINTER :: return_lat(:)
1557    LOGICAL, POINTER :: return_mask(:)
1558    INTEGER, POINTER :: return_index(:)
1559    DOUBLE PRECISION, POINTER :: return_X_lon(:)
1560    DOUBLE PRECISION, POINTER :: return_X_lat(:)
1561    LOGICAL, POINTER :: return_X_mask(:)
1562    INTEGER, POINTER :: return_X_index(:)
1563    DOUBLE PRECISION, POINTER :: return_Y_lon(:)
1564    DOUBLE PRECISION, POINTER :: return_Y_lat(:)
1565    LOGICAL, POINTER :: return_Y_mask(:)
1566    INTEGER, POINTER :: return_Y_index(:)
1567    INTEGER :: domain_proc_rank, domain_proc_size   
1568    INTEGER :: axis_proc_rank, axis_proc_size
1569    INTEGER :: ensemble_proc_size, ensemble_proc_rank
1570
1571    INTEGER :: mpi_rank, mpi_size
1572    INTEGER ::  ierr
1573    INTEGER :: ni,nj,ni_glo,nj_glo
1574    INTEGER :: ibegin,jbegin
1575    INTEGER :: nbp,nbp_glo, offset
1576    DOUBLE PRECISION, ALLOCATABLE :: lon_glo(:), lat_glo(:), lon(:), lat(:)
1577    LOGICAL,ALLOCATABLE :: mask(:)
1578    INTEGER :: i,j, ij, pos, i_glo, j_glo, ij_begin, ij_end
1579       
1580    CALL MPI_COMM_RANK(comm,mpi_rank,ierr)
1581    CALL MPI_COMM_SIZE(comm,mpi_size,ierr)
1582
1583    CALL get_decomposition(comm, params, domain_proc_size, domain_proc_rank, axis_proc_size, axis_proc_rank, ensemble_proc_size, ensemble_proc_rank)
1584    ni_glo=params%ni
1585    nj_glo=params%nj
1586    nbp_glo=ni_glo*nj_glo
1587    nbp=nbp_glo/domain_proc_size
1588    IF (domain_proc_rank < MOD(nbp_glo,domain_proc_size) ) THEN
1589     nbp=nbp+1
1590     offset=nbp*domain_proc_rank
1591    ELSE
1592      offset=nbp*domain_proc_rank + MOD(nbp_glo, domain_proc_size)
1593    ENDIF
1594   
1595   
1596    ibegin=0 ; ni=ni_glo
1597    jbegin=offset / ni_glo
1598   
1599    nj = (offset+nbp-1) / ni_glo - jbegin + 1 
1600   
1601    offset=offset-jbegin*ni
1602
1603    ij_begin=offset+jbegin*ni
1604    ij_end=ij_begin+nbp-1
1605   
1606    ALLOCATE(lon(0:ni-1), lat(0:nj-1), mask(0:ni*nj-1))
1607    mask(:)=.FALSE.
1608    mask(offset:offset+nbp-1)=.TRUE.
1609   
1610    ALLOCATE(lon_glo(0:ni_glo-1), lat_glo(0:nj_glo-1))
1611   
1612    DO i=0,ni_glo-1
1613      lon_glo(i)=-180+(i+0.5)*(360./ni_glo)
1614    ENDDO
1615
1616    DO j=0,nj_glo-1
1617      lat_glo(j)=-90+(j+0.5)*(180./nj_glo)
1618    ENDDO
1619     
1620    lon(:)=lon_glo(:)
1621    lat(:)=lat_glo(jbegin:jbegin+nj-1)
1622
1623    ALLOCATE(return_lon(0:ni*nj-1))
1624    ALLOCATE(return_lat(0:ni*nj-1))
1625    ALLOCATE(return_mask(0:ni*nj-1))
1626
1627    ALLOCATE(return_X_lon(0:ni-1))
1628    ALLOCATE(return_X_lat(0:ni-1))
1629    ALLOCATE(return_X_mask(0:ni-1))
1630
1631    ALLOCATE(return_Y_lon(0:nj-1))
1632    ALLOCATE(return_Y_lat(0:nj-1))
1633    ALLOCATE(return_Y_mask(0:nj-1))
1634
1635
1636     DO j=0,nj-1
1637      DO i=0,ni-1
1638        return_lon(i+j*ni)=lon(i)
1639        return_lat(i+j*ni)=lat(j)
1640      ENDDO
1641    ENDDO
1642
1643    pos=0
1644    DO j=0,nj-1
1645      DO i=0,ni-1
1646        i_glo=i
1647        j_glo=jbegin+j
1648        ij=j_glo*ni_glo+i_glo
1649        IF ( ij>=ij_begin .AND. ij<=ij_end) THEN
1650           IF ((MOD(j_glo,3)==1 .OR. MOD(j_glo,3)==2) .AND. (MOD(i_glo,5)==3 .OR. MOD(i_glo,5)==4)) CYCLE
1651           pos=pos+1
1652        ENDIF
1653      ENDDO
1654   ENDDO
1655
1656   ALLOCATE(return_index(0:pos-1))
1657   return_index(:)=-1
1658   pos=0
1659    DO j=0,nj-1
1660      DO i=0,ni-1
1661        i_glo=i
1662        j_glo=jbegin+j
1663        ij=j_glo*ni_glo+i_glo
1664        IF ( ij>=ij_begin .AND. ij<=ij_end) THEN
1665           IF ((MOD(j_glo,3)==1 .OR. MOD(j_glo,3)==2) .AND. (MOD(i_glo,5)==3 .OR. MOD(i_glo,5)==4)) CYCLE
1666            return_index(pos)=i+j*ni
1667           pos=pos+1
1668        ENDIF
1669      ENDDO
1670   ENDDO     
1671
1672    CALL set_domain_mask(params, return_lon,return_lat, mask)
1673
1674    return_mask=mask
1675
1676    return_X_lat(:)=lat_glo(nj_glo/2)
1677    return_X_lon(:)=lon_glo(:)
1678    CALL set_domain_mask(params, return_X_lon,return_X_lat, return_X_mask)
1679
1680   pos=0
1681    DO i=0,ni-1
1682      i_glo=i
1683      j_glo=nj_glo/2
1684      IF ((MOD(j_glo,3)==1 .OR. MOD(j_glo,3)==2) .AND. (MOD(i_glo,5)==3 .OR. MOD(i_glo,5)==4)) CYCLE
1685      pos=pos+1
1686    ENDDO
1687
1688    ALLOCATE(return_X_index(0:pos-1))
1689    return_X_index(:)=-1
1690    pos=0
1691    DO i=0,ni-1
1692      i_glo=i
1693      j_glo=nj_glo/2
1694      IF ((MOD(j_glo,3)==1 .OR. MOD(j_glo,3)==2) .AND. (MOD(i_glo,5)==3 .OR. MOD(i_glo,5)==4)) CYCLE
1695      return_X_index(pos)=i
1696      pos=pos+1
1697    ENDDO 
1698
1699
1700   
1701    return_Y_lon(:)=lon_glo(ni_glo/2)
1702    return_Y_lat(:)=lat_glo(jbegin:jbegin+nj-1)
1703    CALL set_domain_mask(params, return_Y_lon,return_Y_lat, return_Y_mask)
1704
1705    pos=0
1706    DO j=0,nj-1
1707      i_glo=ni_glo/2
1708      j_glo=j+jbegin
1709      IF ((MOD(j_glo,3)==1 .OR. MOD(j_glo,3)==2) .AND. (MOD(i_glo,5)==3 .OR. MOD(i_glo,5)==4)) CYCLE
1710      pos=pos+1
1711    ENDDO
1712
1713    ALLOCATE(return_Y_index(0:pos-1))
1714    return_Y_index=-1
1715    pos=0
1716    DO j=0,nj-1
1717      i_glo=ni_glo/2
1718      j_glo=j+jbegin
1719      IF ((MOD(j_glo,3)==1 .OR. MOD(j_glo,3)==2) .AND. (MOD(i_glo,5)==3 .OR. MOD(i_glo,5)==4)) CYCLE
1720      return_Y_index(pos)=j
1721      pos=pos+1
1722    ENDDO
1723
1724    return_ni=ni
1725    return_nj=nj
1726
1727    IF (xios_is_valid_domain(TRIM(domain_id))) THEN
1728      CALL xios_set_domain_attr(TRIM(domain_id), type="rectilinear", ni_glo=ni_glo, ibegin=ibegin, ni=ni, nj_glo=nj_glo, jbegin=jbegin, nj=nj)
1729      CALL xios_set_domain_attr(TRIM(domain_id), data_dim=1, data_ni=size(return_index), data_i_index=return_index)
1730      CALL xios_set_domain_attr(TRIM(domain_id), lonvalue_1d=lon, latvalue_1d=lat, mask_1d=mask)
1731    ENDIF
1732   
1733    IF (xios_is_valid_axis(TRIM(domain_id)//"_X")) THEN
1734      CALL xios_set_axis_attr(TRIM(domain_id)//"_X", n_glo=ni_glo, begin=ibegin, n=ni, value=return_X_lon, data_n=size(return_X_index), data_index=return_X_index)
1735    ENDIF
1736
1737    IF (xios_is_valid_axis(TRIM(domain_id)//"_Y")) THEN   
1738      CALL xios_set_axis_attr(TRIM(domain_id)//"_Y", n_glo=nj_glo, begin=jbegin, n=nj, value=return_Y_lat, data_n=size(return_Y_index), data_index=return_Y_index)
1739    ENDIF
1740
1741  END SUBROUTINE init_domain_orchidee
1742
1743
1744
1745  SUBROUTINE init_domain_nemo(domain_id, comm, params, return_ni, return_nj,               &
1746                              return_lon,return_lat,return_mask, return_index,             &
1747                              return_X_lon,return_X_lat, return_X_mask, return_X_index,    &
1748                              return_Y_lon,return_Y_lat, return_Y_mask, return_Y_index)
1749  IMPLICIT NONE
1750    CHARACTER(LEN=*) :: domain_id
1751    TYPE(tmodel_params) :: params
1752    TYPE(xios_context) :: ctx_hdl
1753    INTEGER :: comm
1754    INTEGER :: return_ni
1755    INTEGER :: return_nj
1756    DOUBLE PRECISION, POINTER :: return_lon(:)
1757    DOUBLE PRECISION, POINTER :: return_lat(:)
1758    LOGICAL, POINTER :: return_mask(:)
1759    INTEGER, POINTER :: return_index(:)
1760    DOUBLE PRECISION, POINTER :: return_X_lon(:)
1761    DOUBLE PRECISION, POINTER :: return_X_lat(:)
1762    LOGICAL, POINTER :: return_X_mask(:)
1763    INTEGER, POINTER :: return_X_index(:)
1764    DOUBLE PRECISION, POINTER :: return_Y_lon(:)
1765    DOUBLE PRECISION, POINTER :: return_Y_lat(:)
1766    LOGICAL, POINTER :: return_Y_mask(:)
1767    INTEGER, POINTER :: return_Y_index(:)
1768    INTEGER :: domain_proc_rank, domain_proc_size   
1769    INTEGER :: axis_proc_rank, axis_proc_size
1770    INTEGER :: ensemble_proc_size, ensemble_proc_rank
1771
1772    INTEGER :: mpi_rank, mpi_size
1773    INTEGER ::  ierr
1774    INTEGER :: ni,nj,ni_glo,nj_glo
1775    INTEGER :: ibegin,jbegin
1776    INTEGER :: offset_i, offset_j
1777    DOUBLE PRECISION, ALLOCATABLE :: lon_glo(:), lat_glo(:), bounds_lon_glo(:,:), bounds_lat_glo(:,:)
1778    DOUBLE PRECISION, ALLOCATABLE :: lon(:,:), lat(:,:), bounds_lon(:,:,:), bounds_lat(:,:,:) 
1779    LOGICAL,ALLOCATABLE :: mask(:)
1780    INTEGER :: i,j, ij, n, rank
1781    INTEGER :: nproc_i, nproc_j, nholes, pos_hole
1782    INTEGER,ALLOCATABLE :: size_i(:), begin_i(:), size_j(:), begin_j(:)
1783       
1784    CALL MPI_COMM_RANK(comm,mpi_rank,ierr)
1785    CALL MPI_COMM_SIZE(comm,mpi_size,ierr)
1786
1787    CALL get_decomposition(comm, params, domain_proc_size, domain_proc_rank, axis_proc_size, axis_proc_rank, ensemble_proc_size, ensemble_proc_rank)
1788    ni_glo=params%ni
1789    nj_glo=params%nj
1790
1791    n=INT(SQRT(mpi_size*1.))
1792    nproc_i=n
1793    nproc_j=n
1794    IF ( n*n == mpi_size) THEN
1795    ! do nothing
1796    ELSE IF ( (n+1)*n < mpi_size) THEN
1797      nproc_i=nproc_i+1
1798      nproc_j=nproc_j+1
1799    ELSE
1800      nproc_i=nproc_i+1
1801    ENDIF
1802   
1803    nholes=nproc_i*nproc_j-mpi_size
1804
1805    ALLOCATE(size_i(0:nproc_i-1))
1806    ALLOCATE(begin_i(0:nproc_i-1))
1807    DO i=0,nproc_i-1
1808      size_i(i)=ni_glo/nproc_i
1809      IF (i<MOD(ni_glo,nproc_i)) size_i(i)=size_i(i)+1
1810      IF (i==0) THEN
1811        begin_i(i)=0
1812      ELSE
1813        begin_i(i)=begin_i(i-1)+size_i(i-1)
1814      ENDIF
1815    ENDDO
1816   
1817    ALLOCATE(size_j(0:nproc_j-1))
1818    ALLOCATE(begin_j(0:nproc_j-1))
1819    DO j=0,nproc_i-1
1820      size_j(j)=nj_glo/nproc_j
1821      IF (j<MOD(nj_glo,nproc_j)) size_j(j)=size_j(j)+1
1822      IF (j==0) THEN
1823        begin_j(j)=0
1824      ELSE
1825        begin_j(j)=begin_j(j-1)+size_j(j-1)
1826      ENDIF
1827    ENDDO
1828
1829
1830    pos_hole=0
1831    rank=0
1832    DO j=0,nproc_j-1
1833      DO i=0,nproc_i-1
1834
1835        ij = j*nproc_i + i
1836        IF (pos_hole<nholes) THEN
1837          IF ( MOD(ij,(nproc_i*nproc_j/nholes)) == 0) THEN
1838            pos_hole=pos_hole+1
1839            CYCLE
1840          ENDIF
1841        ENDIF
1842       
1843        IF (mpi_rank==rank) THEN
1844          ibegin = begin_i(i)
1845          ni = size_i(i)
1846          jbegin = begin_j(j)
1847          nj = size_j(j)
1848        ENDIF
1849        rank=rank+1
1850      ENDDO
1851    ENDDO
1852
1853    ALLOCATE(lon_glo(0:ni_glo-1), lat_glo(0:nj_glo-1))
1854    ALLOCATE(bounds_lon_glo(4,0:ni_glo-1), bounds_lat_glo(4,0:nj_glo-1))
1855   
1856    DO i=0,ni_glo-1
1857      lon_glo(i)=-180+(i+0.5)*(360./ni_glo)
1858      bounds_lon_glo(1,i)= -180+(i)*(360./ni_glo)
1859      bounds_lon_glo(2,i)= -180+(i+1)*(360./ni_glo)
1860    ENDDO
1861
1862    DO j=0,nj_glo-1
1863      lat_glo(j)=-90+(j+0.5)*(180./nj_glo)
1864      bounds_lat_glo(1,j)= -90+(j)*(180./nj_glo)
1865      bounds_lat_glo(2,j)= -90+(j+1)*(180./nj_glo)
1866    ENDDO
1867
1868    offset_i=2    ! halo of 2 on i
1869    offset_j=1    ! halo of 1 on j
1870
1871    ALLOCATE(lon(0:ni-1,0:nj-1))
1872    ALLOCATE(lat(0:ni-1,0:nj-1))
1873    ALLOCATE(bounds_lon(4,0:ni-1,0:nj-1))
1874    ALLOCATE(bounds_lat(4,0:ni-1,0:nj-1))
1875!    ALLOCATE(mask(0:ni-1,0:nj-1))
1876   
1877    ALLOCATE(return_lon(0:ni*nj-1))
1878    ALLOCATE(return_lat(0:ni*nj-1))
1879    ALLOCATE(return_mask(0:ni*nj-1))
1880    ALLOCATE(return_index(0:(ni+2*offset_i)*(nj+2*offset_j)-1))
1881
1882    ALLOCATE(return_X_lon(0:ni-1))
1883    ALLOCATE(return_X_lat(0:ni-1))
1884    ALLOCATE(return_X_mask(0:ni-1))
1885    ALLOCATE(return_X_index(0:ni-1))
1886
1887    ALLOCATE(return_Y_lon(0:nj-1))
1888    ALLOCATE(return_Y_lat(0:nj-1))
1889    ALLOCATE(return_Y_mask(0:nj-1))
1890    ALLOCATE(return_Y_index(0:nj-1))
1891   
1892    return_index=-1 
1893    DO j=0,nj-1
1894      DO i=0,ni-1
1895        ij=j*ni+i
1896        return_lon(ij)=lon_glo(ibegin+i)
1897        return_lat(ij)=lat_glo(jbegin+j)
1898        lon(i,j)=return_lon(ij)
1899        lat(i,j)=return_lat(ij)
1900        bounds_lon(1,i,j)=bounds_lon_glo(2,ibegin+i)
1901        bounds_lon(2,i,j)=bounds_lon_glo(1,ibegin+i)
1902        bounds_lon(3,i,j)=bounds_lon_glo(1,ibegin+i)
1903        bounds_lon(4,i,j)=bounds_lon_glo(2,ibegin+i)
1904        bounds_lat(1,i,j)=bounds_lat_glo(1,jbegin+j)
1905        bounds_lat(2,i,j)=bounds_lat_glo(1,jbegin+j)
1906        bounds_lat(3,i,j)=bounds_lat_glo(2,jbegin+j)
1907        bounds_lat(4,i,j)=bounds_lat_glo(2,jbegin+j)
1908
1909        ij=(j+offset_j)*(ni+2*offset_i)+i+offset_i
1910        return_index(ij)=i+j*ni
1911      ENDDO
1912    ENDDO
1913
1914    CALL set_domain_mask(params, return_lon,return_lat, return_mask)
1915
1916    ALLOCATE(return_X_lon(0:ni-1))
1917    ALLOCATE(return_X_lat(0:ni-1))
1918    ALLOCATE(return_X_mask(0:ni-1))
1919    ALLOCATE(return_X_index(0:ni+2*offset_i-1))
1920
1921    return_X_lat(:)=lat_glo(nj_glo/2)
1922    return_X_lon(:)=lon_glo(ibegin:ibegin+ni-1)
1923    CALL set_domain_mask(params, return_X_lon,return_X_lat, return_X_mask)
1924
1925    return_X_index(:)=-1
1926    DO i=0,ni-1
1927      return_X_index(offset_i+i)=i
1928    ENDDO
1929
1930    ALLOCATE(return_Y_lon(0:nj-1))
1931    ALLOCATE(return_Y_lat(0:nj-1))
1932    ALLOCATE(return_Y_mask(0:nj-1))
1933    ALLOCATE(return_Y_index(0:nj+2*offset_j-1))
1934
1935    return_Y_lat(:)=lat_glo(jbegin:jbegin+nj-1)
1936    return_Y_lon(:)=lon_glo(ni_glo/2)
1937    CALL set_domain_mask(params, return_Y_lon,return_Y_lat, return_Y_mask)
1938
1939    return_Y_index(:)=-1
1940    DO j=0,nj-1
1941      return_Y_index(offset_j+j)=j
1942    ENDDO
1943
1944    return_ni=ni
1945    return_nj=nj
1946
1947    IF (xios_is_valid_domain(TRIM(domain_id))) THEN
1948      CALL xios_set_domain_attr(TRIM(domain_id), type="curvilinear", data_dim=2)
1949      CALL xios_set_domain_attr(TRIM(domain_id), ni_glo=ni_glo, ibegin=ibegin, ni=ni, data_ibegin=-offset_i, data_ni=ni+2*offset_i)
1950      CALL xios_set_domain_attr(TRIM(domain_id), nj_glo=nj_glo, jbegin=jbegin, nj=nj, data_jbegin=-offset_j, data_nj=nj+2*offset_j)
1951      CALL xios_set_domain_attr(TRIM(domain_id), data_dim=2, lonvalue_2d=lon, latvalue_2d=lat, mask_1d=return_mask)
1952      CALL xios_set_domain_attr(TRIM(domain_id), bounds_lon_2d=bounds_lon, bounds_lat_2d=bounds_lat, nvertex=4)
1953    ENDIF
1954
1955   
1956    IF (xios_is_valid_axis(TRIM(domain_id)//"_X")) THEN
1957      CALL xios_set_axis_attr(TRIM(domain_id)//"_X", n_glo=ni_glo, begin=ibegin, n=ni, data_begin=-offset_i, data_n=ni+2*offset_i, value=return_X_lon, mask=return_X_mask)
1958!      CALL xios_set_axis_attr(TRIM(domain_id)//"_X", n_glo=ni_glo, begin=ibegin, n=ni, data_index=return_X_index, data_n=ni+2*offset_i, value=return_X_lon)
1959    ENDIF
1960
1961    IF (xios_is_valid_axis(TRIM(domain_id)//"_Y")) THEN   
1962      CALL xios_set_axis_attr(TRIM(domain_id)//"_Y", n_glo=nj_glo, begin=jbegin, n=nj, data_begin=-offset_j, data_n=nj+2*offset_j, value=return_Y_lat, mask=return_Y_mask)
1963!      CALL xios_set_axis_attr(TRIM(domain_id)//"_Y", n_glo=nj_glo, begin=jbegin, n=nj, data_index=return_Y_index, data_n=nj+2*offset_j, value=return_Y_lat, mask=return_Y_mask)
1964    ENDIF
1965
1966  END SUBROUTINE init_domain_nemo
1967
1968
1969
1970
1971 
1972   SUBROUTINE set_domain_mask(params, lon,lat, mask)
1973   IMPLICIT NONE
1974     TYPE(tmodel_params) :: params
1975     DOUBLE PRECISION  :: lon(:)
1976     DOUBLE PRECISION  :: lat(:)
1977     LOGICAL           :: mask(:)
1978     INTEGER :: i,x
1979
1980     mask(:)=.TRUE.
1981     IF (params%domain_mask) THEN
1982       IF (params%domain_mask_type=="cross") THEN
1983         WHERE (lon(:)-2*lat(:)>-10 .AND. lon(:)-2*lat(:) <10) mask(:)=.FALSE. 
1984         WHERE (2*lat(:)+lon(:)>-10 .AND. 2*lat(:)+lon(:)<10) mask(:)=.FALSE.
1985       ELSE IF (params%domain_mask_type=="latitude_band") THEN
1986         WHERE (lat(:)>-30 .AND. lat(:)<30) mask(:)=.FALSE.
1987      ENDIF
1988     ENDIF
1989
1990  END SUBROUTINE set_domain_mask
1991     
1992
1993  SUBROUTINE set_mask3d(grid_id, params, ni, nj, lon,lat, axis_value)
1994  IMPLICIT NONE
1995    CHARACTER(LEN=*) :: grid_id
1996    TYPE(tmodel_params) :: params
1997    INTEGER :: comm
1998    INTEGER :: ni
1999    INTEGER :: nj
2000    DOUBLE PRECISION, POINTER :: lon(:)
2001    DOUBLE PRECISION, POINTER :: lat(:)
2002    INTEGER, POINTER          :: domain_index(:)   
2003    DOUBLE PRECISION, POINTER :: axis_value(:)
2004    INTEGER, POINTER          :: axis_index(:)
2005    INTEGER ::i,j,ij,k,nk
2006    LOGICAL, ALLOCATABLE :: mask3d(:,:,:)
2007    DOUBLE PRECISION :: r
2008
2009    nk=size(axis_value)
2010
2011    ALLOCATE(mask3d(0:ni-1,0:nj-1,0:nk-1))
2012
2013    mask3d=.TRUE.
2014    DO k=0,nk-1
2015      DO j=0,nj-1
2016        DO i=0,ni-1
2017          ij=j*ni+i
2018          r=sqrt((lon(ij)/2)**2 + lat(ij)**2) / ((nk-k)*1./nk) 
2019          if (r < 60) mask3d(i,j,k)=.FALSE.
2020        ENDDO
2021      ENDDO
2022    ENDDO
2023
2024    IF (params%mask3d) CALL  xios_set_grid_attr(grid_id, mask_3d=mask3d)
2025
2026  END SUBROUTINE set_mask3d
2027   
2028  SUBROUTINE init_axis_pressure(axis_id,comm,params, return_value, return_mask, return_index)
2029  IMPLICIT NONE
2030    CHARACTER(LEN=*) :: axis_id
2031    TYPE(tmodel_params) :: params
2032    INTEGER :: comm
2033    DOUBLE PRECISION, POINTER :: return_value(:)
2034    LOGICAL, POINTER          :: return_mask(:)
2035    INTEGER, POINTER          :: return_index(:)
2036   
2037    INTEGER :: nlev_glo
2038    INTEGER :: nlev, begin, end
2039    DOUBLE PRECISION, ALLOCATABLE :: value_glo(:) 
2040    DOUBLE PRECISION, ALLOCATABLE :: bounds_value_glo(:,:) 
2041    DOUBLE PRECISION, ALLOCATABLE :: value(:) 
2042    DOUBLE PRECISION, ALLOCATABLE :: bounds_value(:,:) 
2043    DOUBLE PRECISION :: dp
2044    INTEGER :: i
2045
2046    INTEGER :: domain_proc_rank, domain_proc_size   
2047    INTEGER :: axis_proc_rank, axis_proc_size
2048    INTEGER :: ensemble_proc_size, ensemble_proc_rank
2049
2050    CALL get_decomposition(comm, params, domain_proc_size, domain_proc_rank, axis_proc_size, axis_proc_rank, ensemble_proc_size, ensemble_proc_rank)     
2051
2052    nlev_glo=params%nlev
2053   
2054    ALLOCATE(value_glo(0:nlev_glo-1), bounds_value_glo(2,0:nlev_glo-1) )
2055   
2056    dp=(1-0.1)/(nlev_glo-1)
2057    DO i=0,nlev_glo-1
2058     value_glo(i)=1-i*dp
2059    ENDDO
2060   
2061    bounds_value_glo(1,0)=value_glo(0)-(value_glo(1)-value_glo(0))/2
2062    DO i=1,nlev_glo-1
2063     bounds_value_glo(1,i)=(value_glo(i-1)+value_glo(i)) /2
2064    ENDDO
2065
2066    DO i=0,nlev_glo-2
2067     bounds_value_glo(2,i)=(value_glo(i)+value_glo(i+1)) /2
2068    ENDDO
2069    bounds_value_glo(2,nlev_glo-1)=value_glo(nlev_glo-1)-(value_glo(nlev_glo-2)-value_glo(nlev_glo-1))/2
2070
2071    nlev=nlev_glo/axis_proc_size
2072    IF (axis_proc_rank < MOD(nlev_glo,axis_proc_size)) THEN
2073      nlev=nlev+1
2074      begin= axis_proc_rank*nlev
2075      end=begin+nlev-1
2076    ELSE
2077      begin=MOD(nlev_glo,axis_proc_size)*(nlev+1) + (axis_proc_rank-MOD(nlev_glo,axis_proc_size))*nlev
2078      end=begin+nlev-1
2079    ENDIF
2080
2081    ALLOCATE(value(0:nlev-1), bounds_value(2,0:nlev-1) )
2082    value(:)=value_glo(begin:end)
2083    bounds_value(:,:)=bounds_value_glo(:,begin:end)
2084   
2085    ALLOCATE(return_value(0:nlev-1))
2086    ALLOCATE(return_mask(0:nlev-1))
2087    return_value=value
2088    return_mask=.TRUE.
2089    CALL set_axis_mask(params,value,return_mask)   
2090    CALL xios_set_axis_attr(axis_id, n_glo=nlev_glo, begin=begin, n=nlev, value=value*1000, mask=return_mask, bounds=bounds_value*1000, unit='mb', positive='up')   
2091   
2092
2093    ALLOCATE(return_index(0:nlev-1))
2094
2095    DO i=0,nlev-1
2096      return_index(i)=i
2097    ENDDO 
2098
2099
2100  END SUBROUTINE init_axis_pressure
2101
2102  SUBROUTINE set_axis_mask(params, value, mask)
2103  IMPLICIT NONE
2104    TYPE(tmodel_params) :: params
2105     DOUBLE PRECISION  :: value(:)
2106     LOGICAL           :: mask(:)
2107     INTEGER :: i,x
2108     
2109     mask(:)=.TRUE.
2110     x=size(mask)
2111     IF (params%axis_mask) THEN
2112       DO i=0,x-1
2113         IF (MOD(i,3)==0) mask(i+1)=.FALSE.
2114         IF (MOD(i,4)==0) mask(i+1)=.FALSE.
2115       ENDDO
2116     ENDIF
2117
2118  END SUBROUTINE set_axis_mask 
2119
2120  SUBROUTINE init_scalar(scalar_id, comm, params,  return_mask)
2121  IMPLICIT NONE
2122     CHARACTER(LEN=*) :: scalar_id
2123     TYPE(tmodel_params) :: params
2124     INTEGER             :: comm
2125     LOGICAL             :: return_mask
2126     DOUBLE PRECISION    :: value =10.
2127
2128    CALL set_scalar_mask(comm, params, return_mask)   
2129    CALL xios_set_scalar_attr(scalar_id, value=value, mask=return_mask) 
2130
2131  END SUBROUTINE init_scalar
2132
2133  SUBROUTINE set_scalar_mask(comm, params, mask)
2134   IMPLICIT NONE
2135     TYPE(tmodel_params) :: params
2136     INTEGER             :: comm
2137     LOGICAL             :: mask
2138     INTEGER             :: ierr,rank
2139
2140     mask=.TRUE.
2141     IF (params%scalar_mask) THEN
2142       IF (params%scalar_mask_type=="none") THEN
2143         mask=.TRUE.
2144       ELSE IF (params%scalar_mask_type=="full") THEN
2145         mask=.FALSE.
2146       ELSE IF (params%scalar_mask_type=="root") THEN
2147         CALL MPI_COMM_RANK(comm,rank,ierr)
2148         mask = (rank==0)
2149       ELSE IF (params%scalar_mask_type=="sparse") THEN
2150         CALL MPI_COMM_RANK(comm,rank,ierr)
2151         mask = (MOD(rank,2)==0)
2152      ENDIF
2153     ENDIF
2154
2155  END SUBROUTINE set_scalar_mask
2156
2157  SUBROUTINE init_field2D_academic(comm,params, lon, lat, mask, return_field,            &
2158                                   X_lon, X_lat, X_mask, return_fieldX,                  &
2159                                   Y_lon, Y_lat, Y_mask, return_fieldY, return_fieldXY)
2160  IMPLICIT NONE
2161    TYPE(tmodel_params) :: params
2162    INTEGER :: comm
2163    DOUBLE PRECISION, POINTER :: lon(:)
2164    DOUBLE PRECISION, POINTER :: lat(:)
2165    LOGICAL, POINTER :: mask(:)
2166    DOUBLE PRECISION, POINTER :: return_field(:)
2167
2168    DOUBLE PRECISION, POINTER :: X_lon(:)
2169    DOUBLE PRECISION, POINTER :: X_lat(:)
2170    LOGICAL, POINTER :: X_mask(:)
2171    DOUBLE PRECISION, POINTER :: return_fieldX(:)
2172
2173    DOUBLE PRECISION, POINTER :: Y_lon(:)
2174    DOUBLE PRECISION, POINTER :: Y_lat(:)
2175    LOGICAL, POINTER :: Y_mask(:)
2176    DOUBLE PRECISION, POINTER :: return_fieldY(:)
2177    DOUBLE PRECISION, POINTER :: return_fieldXY(:,:)
2178   
2179    DOUBLE PRECISION, PARAMETER :: coef=2., dp_pi=3.14159265359
2180    DOUBLE PRECISION :: dp_length, dp_conv
2181    INTEGER :: i,j,x,y,xy
2182   
2183     ! Parameters for analytical function
2184    dp_length= 1.2*dp_pi
2185    dp_conv=dp_pi/180.
2186   
2187    xy=size(mask)
2188    x=size(X_mask)
2189    y=size(Y_mask)
2190
2191    ALLOCATE(return_field(0:xy-1))
2192   
2193    DO i=0,xy-1
2194      IF (mask(i)) THEN
2195         return_field(i)=(coef-SIN(dp_pi*(ACOS(COS(lat(i)*dp_conv)*&
2196                   COS(lon(i)*dp_conv))/dp_length)))
2197      ENDIF
2198    ENDDO       
2199
2200
2201    ALLOCATE(return_fieldX(0:x-1))
2202   
2203    DO i=0,x-1
2204      IF (X_mask(i)) THEN
2205         return_fieldX(i)=(coef-SIN(dp_pi*(ACOS(COS(X_lat(i)*dp_conv)*&
2206                            COS(X_lon(i)*dp_conv))/dp_length)))
2207      ENDIF
2208    ENDDO           
2209
2210
2211    ALLOCATE(return_fieldY(0:y-1))
2212   
2213    DO i=0,y-1
2214      IF (Y_mask(i)) THEN
2215         return_fieldY(i)=(coef-SIN(dp_pi*(ACOS(COS(Y_lat(i)*dp_conv)*&
2216                            COS(Y_lon(i)*dp_conv))/dp_length)))
2217      ENDIF
2218    ENDDO
2219
2220    ALLOCATE(return_fieldXY(0:x-1,0:y-1))
2221   
2222    DO j=0,y-1
2223      DO i=0,x-1
2224        IF (Y_mask(j) .AND. X_mask(i)) THEN
2225           return_fieldXY(i,j)=(coef-SIN(dp_pi*(ACOS(COS(Y_lat(j)*dp_conv)*&
2226                                COS(X_lon(i)*dp_conv))/dp_length)))
2227        ENDIF
2228      ENDDO
2229    ENDDO   
2230       
2231  END SUBROUTINE init_field2D_academic
2232
2233
2234  SUBROUTINE init_field2D_constant(comm,params, lon, lat, mask, return_field,             &
2235                                   X_lon, X_lat, X_mask, return_fieldX,                   &
2236                                   Y_lon, Y_lat, Y_mask, return_fieldY, return_fieldXY)
2237  IMPLICIT NONE
2238    TYPE(tmodel_params) :: params
2239    INTEGER :: comm
2240    DOUBLE PRECISION, POINTER :: lon(:)
2241    DOUBLE PRECISION, POINTER :: lat(:)
2242    LOGICAL, POINTER :: mask(:)
2243    DOUBLE PRECISION, POINTER :: return_field(:)
2244   
2245    DOUBLE PRECISION, POINTER :: X_lon(:)
2246    DOUBLE PRECISION, POINTER :: X_lat(:)
2247    LOGICAL, POINTER :: X_mask(:)
2248    DOUBLE PRECISION, POINTER :: return_fieldX(:)
2249
2250    DOUBLE PRECISION, POINTER :: Y_lon(:)
2251    DOUBLE PRECISION, POINTER :: Y_lat(:)
2252    LOGICAL, POINTER :: Y_mask(:)
2253    DOUBLE PRECISION, POINTER :: return_fieldY(:)
2254    DOUBLE PRECISION, POINTER :: return_fieldXY(:,:)
2255    INTEGER :: x,y,xy
2256   
2257    xy=size(mask)
2258    x=size(X_mask)
2259    y=size(Y_mask)
2260       
2261    ALLOCATE(return_field(0:xy-1))
2262    return_field(:)=1
2263
2264    ALLOCATE(return_fieldX(0:x-1))
2265    return_fieldX=1
2266
2267    ALLOCATE(return_fieldY(0:y-1))
2268    return_fieldY=1
2269
2270    ALLOCATE(return_fieldXY(0:x-1,0:y-1))
2271    return_fieldXY=1
2272   
2273  END SUBROUTINE init_field2D_constant
2274
2275  SUBROUTINE init_field2D_rank(comm,params, lon, lat, mask, return_field,         &
2276                               X_lon, X_lat, X_mask, return_fieldX,               &
2277                               Y_lon, Y_lat, Y_mask, return_fieldY, return_fieldXY)
2278
2279  IMPLICIT NONE
2280    TYPE(tmodel_params) :: params
2281    INTEGER :: comm
2282    DOUBLE PRECISION, POINTER :: lon(:)
2283    DOUBLE PRECISION, POINTER :: lat(:)
2284    LOGICAL, POINTER :: mask(:)
2285    DOUBLE PRECISION, POINTER :: return_field(:)
2286
2287    DOUBLE PRECISION, POINTER :: X_lon(:)
2288    DOUBLE PRECISION, POINTER :: X_lat(:)
2289    LOGICAL, POINTER :: X_mask(:)
2290    DOUBLE PRECISION, POINTER :: return_fieldX(:)
2291
2292    DOUBLE PRECISION, POINTER :: Y_lon(:)
2293    DOUBLE PRECISION, POINTER :: Y_lat(:)
2294    LOGICAL, POINTER :: Y_mask(:)
2295    DOUBLE PRECISION, POINTER :: return_fieldY(:)
2296    DOUBLE PRECISION, POINTER :: return_fieldXY(:,:)   
2297    INTEGER ::  rank,ierr
2298    INTEGER :: x,y,xy
2299
2300    CALL MPI_COMM_RANK(comm,rank,ierr)
2301
2302   
2303   
2304    xy=size(mask)
2305    x=size(X_mask)
2306    y=size(Y_mask)
2307       
2308    ALLOCATE(return_field(0:xy-1))
2309    return_field(:)=rank
2310
2311    ALLOCATE(return_fieldX(0:x-1))
2312    return_fieldX=rank
2313
2314    ALLOCATE(return_fieldY(0:y-1))
2315    return_fieldY=rank
2316
2317    ALLOCATE(return_fieldXY(0:x-1,0:y-1))
2318    return_fieldXY=rank
2319
2320  END SUBROUTINE init_field2D_rank
2321
2322
2323
2324   SUBROUTINE get_decomposition(comm, params, domain_proc_size, domain_proc_rank, axis_proc_size, axis_proc_rank, ensemble_proc_size, ensemble_proc_rank)
2325   IMPLICIT NONE
2326     INTEGER,INTENT(IN) :: comm
2327     TYPE(tmodel_params) :: params
2328     INTEGER,INTENT(OUT) :: domain_proc_size
2329     INTEGER,INTENT(OUT) :: domain_proc_rank
2330     INTEGER,INTENT(OUT) :: axis_proc_size
2331     INTEGER,INTENT(OUT) :: axis_proc_rank
2332     INTEGER,INTENT(OUT) :: ensemble_proc_size
2333     INTEGER,INTENT(OUT) :: ensemble_proc_rank
2334
2335     INTEGER :: mpi_rank,mpi_size,rank, ensemble_number
2336     INTEGER :: ierr
2337     INTEGER :: n_domain,n_axis, n_ensemble, min_dist, new_dist, best
2338     INTEGER :: axis_ind, domain_ind
2339     LOGICAL :: axis_layer
2340
2341     CALL MPI_COMM_RANK(comm,mpi_rank,ierr)
2342     CALL MPI_COMM_SIZE(comm,mpi_size,ierr)
2343
2344     n_ensemble = params%ensemble_proc_n
2345     ensemble_proc_size = mpi_size / n_ensemble
2346     IF (  mpi_rank < MOD(mpi_size,n_ensemble) * (ensemble_proc_size+1) ) THEN
2347       ensemble_proc_size=ensemble_proc_size+1
2348       ensemble_proc_rank = MOD(mpi_rank,ensemble_proc_size)
2349       ensemble_number = mpi_rank / ensemble_proc_size
2350     ELSE
2351       ensemble_number = MOD(mpi_size,n_ensemble)
2352       rank =  mpi_rank - MOD(mpi_size,n_ensemble) * (ensemble_proc_size+1)
2353       ensemble_proc_rank= MOD(rank,ensemble_proc_size)
2354       ensemble_number = ensemble_number + rank / ensemble_proc_size
2355     ENDIF
2356
2357     mpi_size=ensemble_proc_size
2358     mpi_rank=ensemble_proc_rank
2359     ensemble_proc_size = n_ensemble
2360     ensemble_proc_rank = ensemble_number
2361
2362    IF (params%axis_proc_n > 0 ) THEN
2363      n_axis=params%axis_proc_n
2364      n_domain = mpi_size / n_axis
2365      axis_layer=.TRUE.
2366    ELSE IF (params%domain_proc_n > 0 ) THEN
2367      n_domain=params%domain_proc_n
2368      n_axis = mpi_size / n_domain
2369      axis_layer=.FALSE.
2370    ELSE
2371      IF (params%axis_proc_frac==0) THEN
2372         params%axis_proc_frac=1
2373         params%domain_proc_frac=mpi_size
2374      ELSE IF (params%domain_proc_frac==0) THEN
2375         params%domain_proc_frac=1
2376         params%axis_proc_frac=mpi_size
2377      ENDIF       
2378   
2379      n_domain = INT(sqrt(params%domain_proc_frac * mpi_size/ params%axis_proc_frac))
2380      n_axis =   INT(sqrt(params%axis_proc_frac * mpi_size/ params%domain_proc_frac))
2381
2382
2383      min_dist= mpi_size - n_domain*n_axis
2384      best=0
2385   
2386      new_dist = mpi_size -(n_domain+1)*n_axis
2387      IF (new_dist < min_dist .AND. new_dist >= 0 ) THEN
2388         min_dist=new_dist
2389         best=1
2390      ENDIF
2391
2392      new_dist=mpi_size-n_domain*(n_axis+1)
2393      IF (new_dist < min_dist .AND. new_dist >= 0 ) THEN
2394         min_dist=new_dist
2395         best=2
2396      ENDIF
2397
2398      IF (best==0) THEN
2399      ELSE IF (best==1) THEN
2400        n_domain=n_domain+1
2401      ELSE IF (best==2) THEN
2402        n_axis=n_axis+1
2403      ENDIF
2404
2405      IF ( MOD(mpi_size,n_axis) <= MOD(mpi_size,n_domain)) axis_layer=.TRUE.
2406
2407    ENDIF
2408   
2409    IF ( axis_layer) THEN
2410      !!! n_axis layer
2411      IF (mpi_rank < MOD(mpi_size,n_axis)*(n_domain+1)) THEN
2412        axis_proc_rank=mpi_rank/(n_domain+1)
2413        domain_proc_rank=MOD(mpi_rank,n_domain+1)
2414        axis_proc_size=n_axis
2415        domain_proc_size=n_domain+1
2416      ELSE
2417        rank=mpi_rank-MOD(mpi_size,n_axis)*(n_domain+1)
2418        axis_proc_size=n_axis
2419        axis_proc_rank=MOD(mpi_size,n_axis)+rank/n_domain
2420        domain_proc_rank=MOD(rank,n_domain)
2421        domain_proc_size=n_domain
2422      ENDIF
2423    ELSE
2424      !!! n_domain column
2425      IF (mpi_rank < MOD(mpi_size,n_domain)*(n_axis+1)) THEN
2426        domain_proc_rank=mpi_rank/(n_axis+1)
2427        axis_proc_rank=MOD(mpi_rank,n_axis+1)
2428        domain_proc_size=n_domain
2429        axis_proc_size=n_axis+1
2430      ELSE
2431        rank=mpi_rank-MOD(mpi_size,n_domain)*(n_axis+1)
2432        domain_proc_size=n_domain
2433        domain_proc_rank=MOD(mpi_size,n_domain)+rank/n_axis
2434        axis_proc_rank=MOD(rank,n_axis)
2435        axis_proc_size=n_axis
2436      ENDIF
2437    ENDIF 
2438
2439
2440  END SUBROUTINE get_decomposition
2441
2442  SUBROUTINE compute_cyclic_distribution(rank, nb_procs, who_i_am)
2443  IMPLICIT NONE
2444    INTEGER,INTENT(IN)  :: rank
2445    INTEGER,INTENT(IN)  :: nb_procs(:)
2446    LOGICAL,INTENT(OUT) :: who_i_am(:)
2447    INTEGER             :: start(SIZE(nb_procs))
2448    INTEGER :: nb_comp 
2449    INTEGER :: nb_client
2450    INTEGER :: nb_server
2451    INTEGER :: current
2452    INTEGER :: current_client
2453    INTEGER :: i,j,k,nq,q,r
2454
2455    who_i_am=.FALSE.
2456    nb_comp = SIZE(nb_procs)
2457    nb_client = SUM(nb_procs(1:nb_comp-1))
2458    nb_server = nb_procs(nb_comp)
2459   
2460    start(1)=0
2461    DO k=2,nb_comp
2462     start(k)=start(k-1)+nb_procs(k-1)
2463    ENDDO
2464
2465    current=0
2466    current_client=0
2467
2468    IF (nb_client >= nb_server) THEN
2469      q=nb_client/nb_server
2470      r=MOD(nb_client,nb_server)
2471       
2472      DO i=1,nb_server
2473        IF (i<=r) THEN ; nq=q+1 ; ELSE ; nq=q ; ENDIF
2474        DO j=1,nq
2475          IF (current==rank) THEN
2476            DO k=1,nb_comp-1
2477              IF (current_client >= start(k) .AND. current_client<start(k+1)) THEN
2478                who_i_am(k)=.TRUE.
2479                RETURN
2480              ENDIF 
2481            ENDDO
2482          ENDIF
2483          current=current+1
2484          current_client=current_client+1
2485        ENDDO
2486
2487        IF (current==rank) THEN
2488          who_i_am(nb_comp)=.TRUE.
2489          RETURN
2490        ENDIF
2491        current=current+1
2492      ENDDO
2493 
2494    ELSE
2495      q=nb_server/nb_client
2496      r=MOD(nb_server,nb_client)
2497
2498      DO i=1,nb_client
2499        IF (i<=r) THEN ; nq=q+1 ; ELSE ; nq=q ; ENDIF
2500        DO j=1,nq
2501          IF (current==rank) THEN
2502            who_i_am(nb_comp)=.TRUE.
2503            RETURN
2504          ENDIF
2505          current=current+1
2506        ENDDO
2507         
2508        IF (current==rank) THEN
2509          DO k=1,nb_comp-1
2510            IF (current_client >= start(k) .AND. current_client<start(k+1)) THEN
2511              who_i_am(k)=.TRUE.
2512              RETURN
2513            ENDIF 
2514          ENDDO
2515        ENDIF
2516        current=current+1
2517        current_client=current_client+1
2518      ENDDO
2519    ENDIF
2520
2521  END SUBROUTINE compute_cyclic_distribution   
2522
2523END PROGRAM generic_testcase
2524
2525
Note: See TracBrowser for help on using the repository browser.