source: XIOS2/trunk/src/test/generic_testcase.f90 @ 2440

Last change on this file since 2440 was 2440, checked in by ymipsl, 19 months ago

Add bounds management for rectilinear domain.
First try.
YM

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