Oasis3-MCT
mod_oasis_method.F90
Go to the documentation of this file.
1 
2 !> High level OASIS user interfaces
3 
5 
7  USE mod_oasis_mem
8  USE mod_oasis_sys
12  USE mod_oasis_part
13  USE mod_oasis_var
16  USE mod_oasis_timer
17  USE mod_oasis_ioshr
18  USE mod_oasis_grid
19  USE mod_oasis_mpi
21  USE mct_mod
22 
23  IMPLICIT NONE
24 
25  private
26 
27  public oasis_init_comp
28  public oasis_terminate
29  public oasis_enddef
30 
31 #ifdef __VERBOSE
32  integer(kind=ip_intwp_p),parameter :: debug=2
33 #else
34  integer(kind=ip_intwp_p),parameter :: debug=1
35 #endif
36  logical :: lg_mpiflag
37  integer(kind=ip_intwp_p) :: mpi_comm_global_world
38 
39 CONTAINS
40 
41 !----------------------------------------------------------------------
42 
43 !> OASIS user init method
44 
45  SUBROUTINE oasis_init_comp(mynummod,cdnam,kinfo,coupled,commworld)
46 
47  !> * This is COLLECTIVE, all pes must call
48 
49  IMPLICIT NONE
50 
51  INTEGER (kind=ip_intwp_p),intent(out) :: mynummod !< component model ID
52  CHARACTER(len=*) ,intent(in) :: cdnam !< model name
53  INTEGER (kind=ip_intwp_p),intent(inout),optional :: kinfo !< return code
54  logical ,intent(in) ,optional :: coupled !< flag to specify whether this component is coupled in oasis
55  integer (kind=ip_intwp_p),intent(in) ,optional :: commworld !< user defined mpi_comm_world to use in oasis
56 ! ---------------------------------------------------------
57  integer(kind=ip_intwp_p) :: ierr
58  INTEGER(kind=ip_intwp_p) :: n,nns,iu
59  integer(kind=ip_intwp_p) :: icolor,ikey
60  CHARACTER(len=ic_med) :: filename,filename2
61  character(len=ic_med) :: pio_type
62  integer(kind=ip_intwp_p) :: pio_stride
63  integer(kind=ip_intwp_p) :: pio_root
64  integer(kind=ip_intwp_p) :: pio_numtasks
65  INTEGER(kind=ip_intwp_p),ALLOCATABLE :: tmparr(:)
66  INTEGER(kind=ip_intwp_p) :: k,i,m,k1,k2
67  INTEGER(kind=ip_intwp_p) :: nt
68  INTEGER(kind=ip_intwp_p) :: nvar
69  INTEGER(kind=ip_intwp_p) :: mpi_size_world
70  INTEGER(kind=ip_intwp_p) :: mpi_rank_world
71  INTEGER(kind=ip_intwp_p) :: mall
72  logical :: found
73  character(len=ic_lvar),pointer :: compnmlist(:)
74  logical,pointer :: coupledlist(:)
75  character(len=ic_lvar) :: tmp_modnam
76  logical :: tmp_modcpl
77  character(len=ic_lvar) :: i_name
78  character(len=*),parameter :: subname = '(oasis_init_comp)'
79 
80  character(len=MPI_MAX_PROCESSOR_NAME), dimension(:), allocatable :: cla_nodes
81  character(len=MPI_MAX_PROCESSOR_NAME) :: cl_node
82  integer :: il_nodelen
83  integer, dimension(:), allocatable :: ila_colors
84 ! ---------------------------------------------------------
85 
86  if (present(kinfo)) then
87  kinfo = oasis_ok
88  endif
89  call oasis_data_zero()
90 
91  oasis_coupled = .true.
92  if (present(coupled)) then
93  oasis_coupled = coupled
94  endif
95 
96  mpi_comm_global_world = mpi_comm_world
97  if (present(commworld)) then
98  mpi_comm_global_world = commworld
99  endif
100 
101  !------------------------
102  !> * Initialize MPI
103  !------------------------
104 
105  lg_mpiflag = .false.
106  CALL mpi_initialized ( lg_mpiflag, ierr )
107  IF ( .NOT. lg_mpiflag ) THEN
108  if (oasis_debug >= 10) WRITE (0,fmt='(A)') subname//': Calling MPI_Init'
109  CALL mpi_init ( ierr )
110  else
111  if (oasis_debug >= 10) WRITE (0,fmt='(A)') subname//': Not Calling MPI_Init'
112  ENDIF
113 
114 ! Initial default for early part of init
115 #ifdef use_comm_MPI1
117 #elif defined use_comm_MPI2
118  mpi_comm_global = ??
119 #endif
120 
121  CALL mpi_comm_size(mpi_comm_global_world,mpi_size_world,ierr)
122  CALL mpi_comm_rank(mpi_comm_global_world,mpi_rank_world,ierr)
123  mpi_rank_global = mpi_rank_world
124 
125  !------------------------
126  !> * Set initial output file, need mpi_rank_world
127  !------------------------
128 
129  iu=-1
130 
131  call oasis_unitsetmin(1024)
132  call oasis_unitsetmax(9999)
133  IF (mpi_rank_world == 0) THEN
134  CALL oasis_unitget(iu)
135  nulprt1 = iu
136  WRITE(filename,'(a,i6.6)') 'nout.',mpi_rank_world
137  OPEN(nulprt1,file=filename)
138  ENDIF
139 
140  !------------------------
141  !> * Initialize namcouple.
142  !> First on rank 0 to write error messages
143  !> then on all other ranks. All tasks will
144  !> read the namcouple file independently.
145  !------------------------
146 
147  IF (mpi_rank_world == 0) THEN
148  call oasis_namcouple_init()
149  endif
151  IF (mpi_rank_world /= 0) THEN
152  call oasis_namcouple_init()
153  endif
159 
160  ! If TIMER_debug < 0 activate LUCIA load balancing analysis
161  lucia_debug = abs(min(namtlogprt,0))
162 
163  !------------------------
164  !> * Check if NFIELDS=0, there is no coupling.
165  ! No information must be written in the debug files as
166  ! the different structures are not allocated
167  !------------------------
168 
169  IF ( nnamcpl == 0 ) THEN
170  IF (mpi_rank_world == 0) THEN
171  WRITE (unit = nulprt1,fmt = *) subname,wstr, &
172  'The models are not exchanging any field ($NFIELDS = 0) '
173  WRITE (unit = nulprt1,fmt = *) &
174  'so we force OASIS_debug = 0 for all processors '
175  oasis_debug = 0
176  CALL oasis_flush(nulprt1)
177  ENDIF
178  ENDIF
179 
180  !------------------------
181  !> * Determine the total number of coupling fields from namcouple.
182  !> Set maxvar parameter and allocate prism_var.
183  ! to avoid a parameter in oasis_def_var and mod_oasis_coupler
184  !------------------------
185 
186  size_namfld=0
187  DO n = 1,nnamcpl
189  ENDDO
190  maxvar = size_namfld * 2 ! multiply by 2 to allow sending to self
191  IF (mpi_rank_world == 0) THEN
192  WRITE (unit = nulprt1,fmt = *) 'Total number of coupling fields :',maxvar
193  CALL oasis_flush(nulprt1)
194  ENDIF
195 
196  ALLOCATE(prism_var(maxvar))
197 
198  !------------------------
199  !> * Store all the names of the fields exchanged in the namcouple
200  ! which can be different of namsrcfld(:) and namdstfld(:) if multiple
201  ! fields are exchanged together
202  !------------------------
203 
204  ALLOCATE(total_namsrcfld(size_namfld))
205  ALLOCATE(total_namdstfld(size_namfld))
206  total_namsrcfld = ''
207  total_namdstfld = ''
208 
209  m=0
210  DO nns = 1,nnamcpl
211  n = namsort2nn(nns)
214  if (k1 /= k2) then
215  WRITE(nulprt1,*) subname,estr,'namcouple fields do not agree in number'
216  WRITE(nulprt1,*) subname,estr,'namsrcfld = ',trim(namsrcfld(n))
217  WRITE(nulprt1,*) subname,estr,'namdstfld = ',trim(namdstfld(n))
218  WRITE(nulprt1,*) subname,estr,'check your namcouple file '
219  call oasis_abort(file=__file__,line=__line__)
220  endif
221  DO i=1,k1
222  m=m+1
223  CALL oasis_string_listgetname(namsrcfld(n),i,i_name)
224  total_namsrcfld(m)=trim(i_name)
225  CALL oasis_string_listgetname(namdstfld(n),i,i_name)
226  total_namdstfld(m)=trim(i_name)
227  ENDDO
228  ENDDO
229  nvar = m
230 
231  IF (oasis_debug >= 15 .and. mpi_rank_world == 0) THEN
232  DO m=1,nvar
233  WRITE (unit = nulprt1,fmt = *) subname,'Coupling fields namsrcfld:',&
234  trim(total_namsrcfld(m))
235  WRITE (unit = nulprt1,fmt = *) subname,'Coupling fields namdstfld:',&
236  trim(total_namdstfld(m))
237  CALL oasis_flush(nulprt1)
238  ENDDO
239  ENDIF
240 
241  !------------------------
242  ! check (not needed anymore)
243  !------------------------
244 
245  if (len_trim(cdnam) > ic_lvar) then
246  WRITE(nulprt1,*) subname,estr,'model name too long = ',trim(cdnam)
247  write(nulprt1,*) subname,estr,'max model name length = ',ic_lvar
248  call oasis_abort(file=__file__,line=__line__)
249  endif
250 
251  !------------------------
252  !> * Gather model names from all tasks to generate active model list on all tasks.
253  !--- Check that the coupled flag from all tasks is consistent for a given model or abort
254  !--- Size of compnm is ic_lvar
255  !------------------------
256 
257  compnm = trim(cdnam)
258  allocate(compnmlist(mpi_size_world))
259  allocate(coupledlist(mpi_size_world))
260  call mpi_gather(compnm, ic_lvar, mpi_character, compnmlist, ic_lvar, mpi_character, 0, mpi_comm_global_world, ierr)
261  call mpi_gather(oasis_coupled, 1, mpi_logical, coupledlist, 1, mpi_logical, 0, mpi_comm_global_world, ierr)
262 
263  prism_nmodels = 0
264  prism_modnam(:) = ' '
265  prism_modcpl(:) = .false.
266  if (mpi_rank_world == 0) then
267  if (oasis_debug >= 15) then
268  do n = 1,mpi_size_world
269  write(nulprt1,*) subname,' compnm gather ',n,trim(compnmlist(n)),coupledlist(n)
270  call oasis_flush(nulprt1)
271  enddo
272  endif
273 
274  !--- generate unique list of models and coupling status
275  !--- check for coupled flag consistency
276  do n = 1,mpi_size_world
277  found = .false.
278  m = 0
279  do while (.not.found .and. m < prism_nmodels)
280  m = m + 1
281  if (compnmlist(n) == prism_modnam(m)) then
282  found = .true.
283  if (coupledlist(n) .neqv. prism_modcpl(m)) then
284  WRITE(nulprt1,*) subname,estr,'inconsistent coupled flag'
285  WRITE(nulprt1,*) subname,estr,'the optional argument, coupled'
286  WRITE(nulprt1,*) subname,estr,'must be identical on all tasks of a component.'
287  call oasis_abort(file=__file__,line=__line__)
288  endif
289  endif
290  enddo
291  if (.not.found) then
293  if (prism_nmodels > prism_mmodels) then
294  WRITE(nulprt1,*) subname,estr,'prism_nmodels too large, increase prism_mmodels in mod_oasis_data'
295  call oasis_abort(file=__file__,line=__line__)
296  endif
297  prism_modnam(prism_nmodels) = trim(compnmlist(n))
298  prism_modcpl(prism_nmodels) = coupledlist(n)
299  endif
300  enddo
301 
302  !--- sort so coupled are first, uncoupled are last
303  !--- makes using only active models via "prism_amodels" easier
305  do n = prism_nmodels,1,-1
306  if (.not.prism_modcpl(n)) then
307  tmp_modnam = prism_modnam(n)
308  tmp_modcpl = prism_modcpl(n)
309  do m = n,prism_nmodels-1
310  prism_modnam(m) = prism_modnam(m+1)
311  prism_modcpl(m) = prism_modcpl(m+1)
312  enddo
313  prism_modnam(prism_nmodels) = tmp_modnam
314  prism_modcpl(prism_nmodels) = tmp_modcpl
316  endif
317  enddo
318 
319  !--- document and check list
320  do n = 1,prism_amodels
321  write(nulprt1,*) subname,' COUPLED models ',n,trim(prism_modnam(n)),prism_modcpl(n)
322  if (.not.prism_modcpl(n)) then
323  WRITE(nulprt1,*) subname,estr,'model expected to be coupled but is not = ',trim(prism_modnam(n))
324  call oasis_abort(file=__file__,line=__line__)
325  endif
326  call oasis_flush(nulprt1)
327  enddo
329  write(nulprt1,*) subname,' UNCOUPLED models ',n,trim(prism_modnam(n)),prism_modcpl(n)
330  if (prism_modcpl(n)) then
331  WRITE(nulprt1,*) subname,estr,'model expected to be uncoupled but is not = ',trim(prism_modnam(n))
332  call oasis_abort(file=__file__,line=__line__)
333  endif
334  call oasis_flush(nulprt1)
335  enddo
336  endif
337 
338  deallocate(compnmlist)
339  deallocate(coupledlist)
340 
341  !------------------------
342  !> * Broadcast the model list to all MPI tasks
343  !------------------------
344  call oasis_mpi_bcast(prism_nmodels,mpi_comm_global_world,subname//' prism_nmodels')
345  call oasis_mpi_bcast(prism_amodels,mpi_comm_global_world,subname//' prism_amodels')
346  call oasis_mpi_bcast(prism_modnam ,mpi_comm_global_world,subname//' prism_modnam')
347  call oasis_mpi_bcast(prism_modcpl ,mpi_comm_global_world,subname//' prism_modcpl')
348 
349  !------------------------
350  !> * Compute compid
351  !------------------------
352 
353  compid = -1
354  do n = 1,prism_nmodels
355  if (trim(cdnam) == trim(prism_modnam(n))) compid = n
356  enddo
357  mynummod = compid
358  IF (mpi_rank_world == 0) THEN
359  WRITE(nulprt1,*) subname, 'cdnam :',trim(cdnam),' mynummod :',mynummod
360  CALL oasis_flush(nulprt1)
361  ENDIF
362 
363 ! tcraig, this should never happen based on logic above
364  if (compid < 0) then
365  WRITE(nulprt1,*) subname,estr,'prism_modnam internal inconsistency = ',trim(cdnam)
366  call oasis_abort(file=__file__,line=__line__)
367  endif
368 
369  !------------------------
370  !> * Re-Set MPI info based on active model tasks
371  ! (need compid for MPI1 COMM_SPLIT)
372  !------------------------
373 
374  mpi_rank_global = -1
375 #ifdef use_comm_MPI1
376 
377  !------------------------
378  !> * Set mpi_comm_local based on compid
379  !------------------------
380 
381  ikey = 0
382  icolor = compid
383  call mpi_comm_split(mpi_comm_global_world,icolor,ikey,mpi_comm_local,ierr)
384 
385  !------------------------
386  !> * Set mpi_comm_global based on oasis_coupled flag
387  !------------------------
388 
389  ikey = 0
390  icolor = 1
391  if (.not.oasis_coupled) icolor = 0
392  call mpi_comm_split(mpi_comm_global_world,icolor,ikey,mpi_comm_global,ierr)
393 !tcx if (.not.oasis_coupled) mpi_comm_global = MPI_COMM_NULL
394 
395 #elif defined use_comm_MPI2
396 
397  mpi_comm_global = ??
399 
400 #endif
401 
402  !------------------------
403  !> * Reset debug levels
404  ! verbose level disabled if load balance analysis
405  !------------------------
406 
407  IF ( lucia_debug > 0 .AND. oasis_debug > 0 ) THEN
408  WRITE (unit = nulprt1,fmt = *) subname,wstr, &
409  ' With LUCIA load balance analysis '
410  WRITE (unit = nulprt1,fmt = *) &
411  ' we set OASIS_debug = 0 '
412  oasis_debug = 0
413  CALL oasis_flush(nulprt1)
414  ENDIF
415 
416  IF (mpi_rank_world == 0) CLOSE(nulprt1)
417 
418  if (.not.oasis_coupled) then
419  return
420  endif
421 
422  CALL mpi_comm_size(mpi_comm_global,mpi_size_global,ierr)
423  CALL mpi_comm_rank(mpi_comm_global,mpi_rank_global,ierr)
424 
425  CALL mpi_comm_size(mpi_comm_local,mpi_size_local,ierr)
426  CALL mpi_comm_rank(mpi_comm_local,mpi_rank_local,ierr)
427  mpi_root_local = 0
428 
429 #ifdef use_comm_MPI1
430 
431  !------------------------
432  !> * Set mpi_comm_map based on node association
433  !------------------------
434 
435  CALL mpi_get_processor_name(mpi_node_name, il_nodelen, ierr)
436 
437  IF (mpi_rank_local == mpi_root_local) THEN
438 
439  ! Prepare working memory on local root
440 
441  ALLOCATE(cla_nodes(mpi_size_local))
442  ALLOCATE(ila_colors(mpi_size_local))
443  cla_nodes(:) = ''
444  ila_colors(:) = -1
445  ELSE
446  ALLOCATE(cla_nodes(1))
447  ALLOCATE(ila_colors(1))
448  END IF
449 
450  CALL mpi_gather (mpi_node_name,mpi_max_processor_name,mpi_char,&
451  & cla_nodes, mpi_max_processor_name,mpi_char,&
453 
454  IF (mpi_rank_local == mpi_root_local) THEN
455 
456  ! Pick only on proc per node
457 
458  DO WHILE (any(ila_colors == -1))
459  cl_node = cla_nodes(minloc(ila_colors,dim=1))
460  ila_colors(minloc(ila_colors,dim=1)) = 1
461  DO i = minloc(ila_colors,dim=1), mpi_size_local
462  IF (ila_colors(i) == -1 .AND. cla_nodes(i) == cl_node)&
463  & ila_colors(i) = 0
464  END DO
465  END DO
466  END IF
467 
468  icolor = 0
469  CALL mpi_scatter (ila_colors,1,mpi_int,&
470  & icolor, 1,mpi_int,&
472 
473  mpi_in_map = icolor == 1
474 
475  ikey = 1
476  CALL mpi_comm_split(mpi_comm_local,icolor,ikey,mpi_comm_map,ierr)
477 
478  IF (mpi_in_map) THEN
479  CALL mpi_comm_size(mpi_comm_map,mpi_size_map,ierr)
480  CALL mpi_comm_rank(mpi_comm_map,mpi_rank_map,ierr)
481  END IF
482 
483  IF (mpi_rank_local == mpi_root_local) THEN
484 
485  ! Set the root of the mapping subcommunicator on the
486  ! local communicator root process
487 
489 
490  END IF
491 
492  ! Free work memory on local root
493 
494  DEALLOCATE(cla_nodes)
495  DEALLOCATE(ila_colors)
496 
497 
498 #elif defined use_comm_MPI2
499 
500  mpi_comm_map = ??
501  mpi_in_map = ??
502 
503 #endif
504  !------------------------
505  !> * Open log files
506  !------------------------
507 
508  iu=-1
509  CALL oasis_unitget(iu)
510  nulprt=iu
511  IF (oasis_debug <= 1) THEN
512  WRITE(filename ,'(a,i2.2)') 'debug.root.',compid
513  WRITE(filename2,'(a,i2.2)') 'debug.notroot.',compid
514  IF (mpi_rank_local == 0) THEN
515  OPEN(nulprt,file=filename,status='REPLACE')
516  WRITE(nulprt,'(2a,2i8)') subname,' OASIS RUNNING '
517  WRITE(nulprt,'(2a,2i8)') subname,' OPEN debug file for pe, unit :',mpi_rank_local,nulprt
518  call oasis_flush(nulprt)
519  ENDIF
520  IF (mpi_rank_local == 1) THEN
521  OPEN(nulprt,file=filename2,status='REPLACE')
522  WRITE(nulprt,'(2a,2i8)') subname,' OASIS RUNNING '
523  WRITE(nulprt,'(2a,2i8)') subname,' OPEN debug file for pe, unit :',mpi_rank_local,nulprt
524  CALL oasis_flush(nulprt)
525  ENDIF
526 
528 
529  IF (mpi_rank_local > 1) THEN
530  OPEN(nulprt,file=filename2,position='APPEND')
531  !WRITE(nulprt,'(2a,2i8)') subname,' OASIS RUNNING '
532  !WRITE(nulprt,'(2a,2i8)') subname,' OPEN debug file for pe, unit :',mpi_rank_local,nulprt
533  !CALL oasis_flush(nulprt)
534  ENDIF
535  ELSE
536  WRITE(filename,'(a,i2.2,a,i6.6)') 'debug.',compid,'.',mpi_rank_local
537  OPEN(nulprt,file=filename,status='REPLACE')
538  WRITE(nulprt,'(2a,2i8)') subname,' OPEN debug file, for pe, unit :',mpi_rank_local,nulprt
539  CALL oasis_flush(nulprt)
540  ENDIF
541 
542  IF ( (oasis_debug == 1) .AND. (mpi_rank_local == 0)) oasis_debug=10
543 
544  IF (oasis_debug >= 2) THEN
545  WRITE(nulprt,'(3a,i8)') subname,' model compid ',trim(cdnam),compid
546  CALL oasis_flush(nulprt)
547  ENDIF
548 
549  iu=-1
550  CALL oasis_unitget(iu)
551  ! If load balance analysis, new log files opened (lucia.*)
552  IF ( lucia_debug > 0 ) THEN
553  IF (mpi_size_local < 20 ) THEN
554  nullucia=iu
555  ! Open LUCIA log file on a subset of process only
556  ELSE IF (mpi_size_local < 100 .AND. mod(mpi_rank_local,mpi_size_local/5) == 0 ) THEN
557  nullucia=iu
558  ELSE IF (mpi_size_local >= 100 .AND. mod(mpi_rank_local,mpi_size_local/20) == 0 ) THEN
559  nullucia=iu
560  ELSE
561  nullucia = 0
562  ENDIF
563  ! Define log file name and open it
564  IF (nullucia /= 0) THEN
565  WRITE(filename,'(a,i2.2,a,i6.6)') 'lucia.',compid,'.',mpi_rank_local
566  OPEN(nullucia,file=filename,status='REPLACE')
567 ! WRITE(nullucia,'(2a,2i8)') subname,' OPEN LUCIA load balancing analysis file for pe, unit :',mpi_size_local,nullucia
568 ! CALL oasis_flush(nullucia)
569  ENDIF
570  ENDIF
571 
572  call oasis_debug_enter(subname)
573 
574  !------------------------
575  !> * Set mpi_root_global
576  ! (after nulprt set)
577  !------------------------
578 
580 
581  !------------------------
582  !--- PIO
583  !------------------------
584 #if (PIO_DEFINED)
585 ! tcraig, not working as of Oct 2011
586  pio_type = 'netcdf'
587  pio_stride = -99
588  pio_root = -99
589  pio_numtasks = -99
590  call oasis_ioshr_init(mpi_comm_local,pio_type,pio_stride,pio_root,pio_numtasks)
591 #endif
592 
593  !------------------------
594  !> * Memory Initialization
595  !------------------------
596 
597  IF (oasis_debug >= 2) THEN
598  CALL oasis_mem_init(nulprt)
599  CALL oasis_mem_print(nulprt,subname)
600  ENDIF
601 
602  !------------------------
603  !> * Timer Initialization
604  !------------------------
605 
606  ! Allocate timer memory based on maxvar
607  nt = 7*maxvar+100
608  call oasis_timer_init (trim(cdnam), trim(cdnam)//'.timers',nt)
609  call oasis_timer_start('total')
610  call oasis_timer_start('init_thru_enddef')
611 
612  !------------------------
613  !> * Diagnostics
614  !------------------------
615 
616  if (oasis_debug >= 15) then
617  write(nulprt,*) subname,' compid = ',compid
618  write(nulprt,*) subname,' compnm = ',trim(compnm)
619  write(nulprt,*) subname,' node name = ',trim(mpi_node_name)
620  write(nulprt,*) subname,' mpi_comm_world = ',mpi_comm_global_world
621  write(nulprt,*) subname,' mpi_comm_global= ',mpi_comm_global
622  write(nulprt,*) subname,' size_global= ',mpi_size_global
623  write(nulprt,*) subname,' rank_global= ',mpi_rank_global
624  write(nulprt,*) subname,' mpi_comm_local = ',mpi_comm_local
625  write(nulprt,*) subname,' size_local = ',mpi_size_local
626  write(nulprt,*) subname,' rank_local = ',mpi_rank_local
627  write(nulprt,*) subname,' root_local = ',mpi_root_local
628  write(nulprt,*) subname,' mpi_in_map = ',mpi_in_map
629  write(nulprt,*) subname,' mpi_comm_map = ',mpi_comm_map
630  write(nulprt,*) subname,' size_map = ',mpi_size_map
631  write(nulprt,*) subname,' rank_map = ',mpi_rank_map
632  write(nulprt,*) subname,' root_map = ',mpi_root_map
633  write(nulprt,*) subname,' OASIS_debug = ',oasis_debug
634  do n = 1,prism_amodels
635  write(nulprt,*) subname,' n,prism_model,root = ',&
636  n,trim(prism_modnam(n)),mpi_root_global(n)
637  enddo
638  call oasis_flush(nulprt)
639  endif
640 
641  IF ( lucia_debug > 0 ) THEN
642  ! We stop all process to read clock time (almost) synchroneously
644  IF ( nullucia /= 0 ) THEN
645  WRITE(nullucia, fmt='(A,F16.5)') 'Balance: IT ', mpi_wtime()
646  WRITE(nullucia, fmt='(A12,A)' ) 'Balance: MD ', trim(compnm)
647  call oasis_flush(nullucia)
648  ELSE
649  ! Since now, non printing process do not participate to load balance analysis
650  lucia_debug = 0
651  ENDIF
652  ENDIF
653 
654  call oasis_debug_exit(subname)
655 
656  END SUBROUTINE oasis_init_comp
657 
658 !----------------------------------------------------------------------
659 
660 !> OASIS user finalize method
661 
662  SUBROUTINE oasis_terminate(kinfo)
664  IMPLICIT NONE
665 
666  INTEGER (kind=ip_intwp_p),intent(inout),optional :: kinfo !< return code
667 ! ---------------------------------------------------------
668  integer(kind=ip_intwp_p) :: ierr
669  character(len=*),parameter :: subname = '(oasis_terminate)'
670 ! ---------------------------------------------------------
671 
672  call oasis_debug_enter(subname)
673  if (.not. oasis_coupled) then
674  call oasis_debug_exit(subname)
675  return
676  endif
677 
678  if (present(kinfo)) then
679  kinfo = oasis_ok
680  endif
681 
682  !------------------------
683  !> * Print timer information
684  !------------------------
685 
686  call oasis_timer_stop('total')
687  call oasis_timer_print()
688 
689  !------------------------
690  !> * Call MPI finalize
691  !------------------------
692 
693  IF ( .NOT. lg_mpiflag ) THEN
694  IF (oasis_debug >= 2) THEN
695  WRITE (nulprt,fmt='(A)') subname//': Calling MPI_Finalize'
696  CALL oasis_flush(nulprt)
697  ENDIF
698  CALL mpi_finalize ( ierr )
699  else
700  IF (oasis_debug >= 2) THEN
701  WRITE (nulprt,fmt='(A)') subname//': Not Calling MPI_Finalize'
702  CALL oasis_flush(nulprt)
703  ENDIF
704  ENDIF
705 
706  !------------------------
707  !> * Write SUCCESSFUL RUN
708  !------------------------
709  IF (oasis_debug >= 2) THEN
710  CALL oasis_mem_print(nulprt,subname)
711  ENDIF
712 
713  IF (mpi_rank_local == 0) THEN
714  WRITE(nulprt,*) subname,' SUCCESSFUL RUN'
715  CALL oasis_flush(nulprt)
716  ENDIF
717 
718  call oasis_debug_exit(subname)
719 
720  CALL oasis_flush(nulprt)
721  close(nulprt)
722 
723  END SUBROUTINE oasis_terminate
724 
725 !----------------------------------------------------------------------
726 
727 !> OASIS user interface specifying the OASIS definition phase is complete
728 
729  SUBROUTINE oasis_enddef(kinfo)
731  IMPLICIT NONE
732 
733  INTEGER (kind=ip_intwp_p),intent(inout),optional :: kinfo !< return code
734 ! ---------------------------------------------------------
735  integer (kind=ip_intwp_p) :: n
736  integer (kind=ip_intwp_p) :: lkinfo
737  integer (kind=ip_intwp_p) :: icpl, ierr
738  integer (kind=ip_intwp_p) :: newcomm
739  logical, parameter :: local_timers_on = .false.
740  character(len=*),parameter :: subname = '(oasis_enddef)'
741 ! ---------------------------------------------------------
742 
743  call oasis_debug_enter(subname)
744 
745  if (.not. oasis_coupled) then
746  call oasis_debug_exit(subname)
747  return
748  endif
749 
750  lkinfo = oasis_ok
751 
752  if (local_timers_on .and. mpi_comm_local /= mpi_comm_null) then
753  call oasis_timer_start('oasis_enddef_barrier')
754  call oasis_mpi_barrier(mpi_comm_local, subname)
755  call oasis_timer_stop('oasis_enddef_barrier')
756  endif
757 
758  CALL oasis_timer_start ('oasis_enddef')
759  if (local_timers_on) call oasis_timer_start('oasis_enddef_prep')
760 
761  !------------------------
762  !> * Check enddef called only once per task
763  !------------------------
764 
765  if (enddef_called) then
766  write(nulprt,*) subname,estr,'enddef called already'
767  call oasis_abort(file=__file__,line=__line__)
768  endif
769  enddef_called = .true.
770 
771  IF (oasis_debug >= 2) THEN
772  CALL oasis_mem_print(nulprt,subname//':start')
773  ENDIF
774 
775  !------------------------
776  !> * Reset mpi_comm_global because active tasks might have been excluded
777  !--- for changes to mpi_comm_local since init
778  !------------------------
779 
780  icpl = mpi_undefined
781  if (mpi_comm_local /= mpi_comm_null) icpl = 1
782  CALL mpi_comm_split(mpi_comm_global,icpl,1,newcomm,ierr)
783  mpi_comm_global = newcomm
784 
785  !------------------------
786  !> * For active tasks only
787  !------------------------
788 
789  if (local_timers_on) call oasis_timer_stop('oasis_enddef_prep')
790 
791  if (mpi_comm_global /= mpi_comm_null) then
792 
793  if (local_timers_on) call oasis_timer_start('oasis_enddef_prep2')
794 
795  !------------------------
796  !> * Update mpi_comm_global
797  !------------------------
798 
799  CALL mpi_comm_size(mpi_comm_global,mpi_size_global,ierr)
800  CALL mpi_comm_rank(mpi_comm_global,mpi_rank_global,ierr)
801 
802  !------------------------
803  !> * Update mpi_root_global
804  !------------------------
805 
807 
808  !------------------------
809  !> * Document
810  !------------------------
811 
812  if (oasis_debug >= 2) then
813  write(nulprt,*) subname,' compid = ',compid
814  write(nulprt,*) subname,' compnm = ',trim(compnm)
815  write(nulprt,*) subname,' mpi_comm_world = ',mpi_comm_global_world
816  write(nulprt,*) subname,' mpi_comm_global= ',mpi_comm_global
817  write(nulprt,*) subname,' size_global= ',mpi_size_global
818  write(nulprt,*) subname,' rank_global= ',mpi_rank_global
819  write(nulprt,*) subname,' mpi_comm_local = ',mpi_comm_local
820  write(nulprt,*) subname,' size_local = ',mpi_size_local
821  write(nulprt,*) subname,' rank_local = ',mpi_rank_local
822  write(nulprt,*) subname,' root_local = ',mpi_root_local
823  write(nulprt,*) subname,' OASIS_debug = ',oasis_debug
824  do n = 1,prism_amodels
825  write(nulprt,*) subname,' n,prism_model,root = ',&
826  n,trim(prism_modnam(n)),mpi_root_global(n)
827  enddo
828  CALL oasis_flush(nulprt)
829  endif
830 
831  if (local_timers_on) call oasis_timer_stop('oasis_enddef_prep2')
832 
833  !------------------------
834  !> * Reconcile partitions, call part_setup
835  !--- generate gsmaps from partitions
836  !------------------------
837 
838  if (local_timers_on) call oasis_timer_start('oasis_enddef_part_setup')
839  call oasis_part_setup()
840  IF (oasis_debug >= 2) THEN
841  CALL oasis_mem_print(nulprt,subname//':part_setup')
842  ENDIF
843  if (local_timers_on) call oasis_timer_stop('oasis_enddef_part_setup')
844 
845  !------------------------
846  !> * Reconcile variables, call var_setup
847  !------------------------
848 
849  if (local_timers_on) call oasis_timer_start('oasis_enddef_var_setup')
850  call oasis_var_setup()
851  IF (oasis_debug >= 2) THEN
852  CALL oasis_mem_print(nulprt,subname//':var_setup')
853  ENDIF
854  if (local_timers_on) call oasis_timer_stop('oasis_enddef_var_setup')
855 
856  !------------------------
857  !> * Write grid info to files one model at a time
858  !------------------------
859 
860  if (local_timers_on) call oasis_timer_start('oasis_enddef_write2files')
862  do n = 1,prism_amodels
863  if (compid == n) then
864  call oasis_write2files()
865  endif
867  enddo
868  IF (oasis_debug >= 2) THEN
869  CALL oasis_mem_print(nulprt,subname//':write2files')
870  ENDIF
871  if (local_timers_on) call oasis_timer_stop('oasis_enddef_write2files')
872 
873  !------------------------
874  !> * MCT Initialization
875  !------------------------
876 
877  if (local_timers_on) call oasis_timer_start('oasis_enddef_mctworldinit')
879  IF (oasis_debug >= 2) THEN
880  WRITE(nulprt,*) subname, ' done mct_world_init '
881  CALL oasis_flush(nulprt)
882  ENDIF
883  if (local_timers_on) call oasis_timer_stop('oasis_enddef_mctworldinit')
884 
885  !------------------------
886  !> * Initialize coupling via call to coupler_setup
887  !------------------------
888 
889  if (local_timers_on) call oasis_timer_start('oasis_enddef_coupler_setup')
890  call oasis_coupler_setup()
891  IF (oasis_debug >= 2) THEN
892  WRITE(nulprt,*) subname, ' done prism_coupler_setup '
893  CALL oasis_flush(nulprt)
894  ENDIF
895  IF (oasis_debug >= 2) THEN
896  CALL oasis_mem_print(nulprt,subname//':coupler_setup')
897  ENDIF
898  if (local_timers_on) call oasis_timer_stop('oasis_enddef_coupler_setup')
899 
900  !------------------------
901  !> * Call advance_init to initialize coupling fields from restarts
902  !------------------------
903 
904  if (local_timers_on) call oasis_timer_start('oasis_enddef_advance_init')
905  call oasis_advance_init(lkinfo)
906  IF (oasis_debug >= 2) THEN
907  WRITE(nulprt,*) subname, ' done prism_advance_init '
908  CALL oasis_flush(nulprt)
909  ENDIF
910  IF (oasis_debug >= 2) THEN
911  CALL oasis_mem_print(nulprt,subname//':advance_init')
912  ENDIF
913  if (local_timers_on) call oasis_timer_stop('oasis_enddef_advance_init')
914 
915  endif ! (mpi_comm_local /= MPI_COMM_NULL)
916 
917  !--- Force OASIS_OK here rather than anything else ---
918 
919  if (local_timers_on) call oasis_timer_start('oasis_enddef_last')
920  if (present(kinfo)) then
921  kinfo = oasis_ok
922  endif
923  CALL oasis_timer_stop ('oasis_enddef')
924  call oasis_timer_stop('init_thru_enddef')
925 
926  IF (oasis_debug >= 2) THEN
927  CALL oasis_mem_print(nulprt,subname//':end')
928  ENDIF
929  if (local_timers_on) call oasis_timer_stop('oasis_enddef_last')
930 
931  call oasis_debug_exit(subname)
932 
933  END SUBROUTINE oasis_enddef
934 !----------------------------------------------------------------------
935 
936 !> Local method to compute each models' global task ids, exists for reuse in enddef
937 
938  SUBROUTINE mod_oasis_setrootglobal()
940  INTEGER(kind=ip_intwp_p) :: n, ierr
941  INTEGER(kind=ip_intwp_p),ALLOCATABLE :: tmparr(:)
942  character(len=*),parameter :: subname = '(oasis_setrootglobal)'
943 
944  !------------------------
945  !--- set mpi_root_global
946  !------------------------
947 
948  if (allocated(mpi_root_global)) then
949  deallocate(mpi_root_global)
950  endif
951  allocate(mpi_root_global(prism_amodels))
952  allocate(tmparr(prism_amodels))
953  tmparr = -1
954  do n = 1,prism_amodels
955  if (compid == n .and. mpi_rank_local == mpi_root_local) then
956  tmparr(n) = mpi_rank_global
957  endif
958  enddo
959  call oasis_mpi_max(tmparr,mpi_root_global,mpi_comm_global, &
960  string=subname//':mpi_root_global',all=.true.)
961  deallocate(tmparr)
962 
963  do n = 1,prism_amodels
964  IF (mpi_root_global(n) < 0) THEN
965  WRITE(nulprt,*) subname,estr,'global root invalid, check couplcomm for active tasks'
966  call oasis_abort(file=__file__,line=__line__)
967  ENDIF
968  enddo
969 
970 END SUBROUTINE mod_oasis_setrootglobal
971 !----------------------------------------------------------------------
972 
973 END MODULE mod_oasis_method
character(len=jpeighty), dimension(:), pointer, public namsrcfld
list of src fields
System type methods.
Provides a common location for several OASIS variables.
integer(kind=ip_i4_p), public namuntmin
namcouple min IO unit value
integer(kind=ip_i4_p), public nnamcpl
number of namcouple inputs
integer(kind=ip_i4_p), public namtlogprt
namcouple ntlogprt value
integer(kind=ip_i4_p) mpi_comm_map
integer(kind=ip_intwp_p), parameter oasis_ok
subroutine, public oasis_mem_print(iunit, string)
Print memory use.
integer(kind=ip_i4_p) lucia_debug
Provides methods for querying memory use.
subroutine, public oasis_init_comp(mynummod, cdnam, kinfo, coupled, commworld)
OASIS user init method.
integer(kind=ip_i4_p) mpi_rank_map
integer(kind=ip_i4_p) mpi_size_local
subroutine, public oasis_write2files()
Interface that actually writes fields to grid files.
integer(kind=ip_i4_p) size_namfld
integer(kind=ip_intwp_p) nulprt
Generic overloaded interface into MPI broadcast.
logical, dimension(prism_mmodels) prism_modcpl
integer(kind=ip_i4_p) mpi_root_map
integer(kind=ip_i4_p) mpi_comm_global
subroutine, public oasis_abort(id_compid, cd_routine, cd_message, file, line, rcode)
OASIS abort method, publically available to users.
integer(kind=ip_intwp_p) nulprt1
character(len=jpeighty), dimension(:), pointer, public namdstfld
list of dst fields
subroutine, public oasis_string_listgetname(list, k, name, rc)
Get name of k-th field in list.
integer(kind=ip_i4_p), public namlogprt
namcouple nlogprt value
subroutine, public oasis_mem_init(iunit)
Initialize memory conversion to MB.
integer(kind=ip_i4_p) compid
subroutine, public oasis_timer_init(app, file, nt)
Initializes the timer methods, called once in an application.
integer(kind=ip_intwp_p), parameter debug
Initialize the OASIS coupler infrastructure.
integer(kind=ip_i4_p) mpi_rank_local
Defines kinds for OASIS.
integer(kind=ip_i4_p) mpi_size_global
integer(kind=ip_i4_p) prism_amodels
Character string manipulation methods.
integer(kind=ip_intwp_p) nullucia
Provides a generic and simpler interface into MPI calls for OASIS.
character(len=ic_lvar), dimension(:), pointer total_namsrcfld
integer(kind=ip_i4_p) prism_nmodels
subroutine, public oasis_terminate(kinfo)
OASIS user finalize method.
logical, parameter local_timers_on
subroutine, public oasis_namcouple_init()
Reads the namcouple.
integer(kind=ip_i4_p) mpi_root_local
subroutine, public oasis_debug_enter(string)
Used when a subroutine is entered, write info to log file at some debug level.
integer(kind=ip_i4_p), public namuntmax
namcouple max IO unit value
character(len=mpi_max_processor_name) mpi_node_name
OASIS partition data and methods.
integer(kind=ip_i4_p) mpi_rank_global
subroutine, public oasis_advance_init(kinfo)
Initializes the OASIS fields.
subroutine, public oasis_unitsetmin(uio)
Set the minimum unit number allowed.
integer(kind=ip_i4_p), dimension(:), allocatable mpi_root_global
OASIS grid data and methods.
Defines parameters for OASIS.
subroutine, public oasis_timer_print(timer_label)
Print timers.
character(len=ic_lvar), dimension(:), pointer total_namdstfld
OASIS variable data and methods.
character(len=ic_lvar) compnm
subroutine, public oasis_timer_start(timer_label, barrier)
Start a timer.
integer(kind=ip_i4_p) oasis_debug
subroutine, public oasis_timer_stop(timer_label)
Stop a timer.
character(len= *), parameter, public estr
integer(kind=ip_i4_p) mpi_comm_local
integer(kind=ip_intwp_p) mpi_comm_global_world
integer function, public oasis_string_listgetnum(str)
return number of fields in string list
subroutine, public oasis_mpi_barrier(comm, string)
Call MPI_BARRIER for a particular communicator.
integer(kind=ip_i4_p), dimension(:), pointer, public namsort2nn
sorted namcpl for sort, define nn order, computed later
subroutine, public oasis_part_setup()
Synchronize partitions across all tasks, called at oasis enddef.
integer, parameter ic_lvar
subroutine, public oasis_unitget(uio)
Get a free unit number.
subroutine, public oasis_enddef(kinfo)
OASIS user interface specifying the OASIS definition phase is complete.
integer(kind=ip_i4_p), parameter prism_mmodels
logical, public allow_no_restart
flag to allow no restart files at startup
subroutine mod_oasis_setrootglobal()
Local method to compute each models&#39; global task ids, exists for reuse in enddef. ...
Advances the OASIS coupling.
subroutine, public oasis_flush(nu)
Flushes output to file.
IO interfaces based on pio (not supported yet)
subroutine oasis_data_zero()
subroutine, public oasis_coupler_setup()
Main routine to setup couplers.
Performance timer methods.
subroutine, public oasis_var_setup()
Synchronize variables across all tasks, called at oasis enddef.
integer(ip_intwp_p), public maxvar
number of potential variables, derived from namcouple input
type(prism_var_type), dimension(:), pointer, public prism_var
list of defined variables
Reads the namcouple file for use in OASIS.
High level OASIS user interfaces.
subroutine, public oasis_unitsetmax(uio)
Set the maximum unit number allowed.
logical, public namnorest
namcouple allow no restarts
integer(kind=ip_i4_p) mpi_size_map
subroutine, public oasis_debug_exit(string)
Used when a subroutine is exited, write info to log file at some debug level.
character(len=ic_lvar), dimension(prism_mmodels) prism_modnam
integer(kind=ip_i4_p) timer_debug
character(len= *), parameter, public wstr