Oasis3-MCT
mod_oasis_sys.F90
Go to the documentation of this file.
1 
2 !> System type methods
3 
5 
8 
9  IMPLICIT NONE
10 
11  character(len=*),parameter,public :: astr = ' ABORT: ' ! abort string
12  character(len=*),parameter,public :: estr = ' ERROR: ' ! error string
13  character(len=*),parameter,public :: wstr = ' WARNING: ' ! warning string
14 
15  private
16 
17  public oasis_abort
18  public oasis_flush
19  public oasis_unitsetmin
20  public oasis_unitsetmax
21  public oasis_unitget
22  public oasis_unitfree
23  public oasis_debug_enter
24  public oasis_debug_exit
25  public oasis_debug_note
26  public oasis_sys_sortc
27  public oasis_sys_sorti
28  public oasis_sys_sortikey
29 
30  integer(ip_intwp_p),save :: minion = 1024
31  integer(ip_intwp_p),save :: maxion = 9999
32  integer(ip_intwp_p),parameter :: tree_delta = 2
33  integer(ip_intwp_p),save :: tree_indent = 0
34 
35 !--------------------------------------------------------------------
36 CONTAINS
37 !--------------------------------------------------------------------
38 
39 !--------------------------------------------------------------------
40 
41 !> OASIS abort method, publically available to users
42 
43 SUBROUTINE oasis_abort(id_compid, cd_routine, cd_message, file, line, rcode)
44 
45  IMPLICIT NONE
46 !--------------------------------------------------------------------
47  INTEGER(kind=ip_intwp_p),INTENT(in),optional :: id_compid !< component id
48  CHARACTER(len=*), INTENT(in),optional :: cd_routine !< string defining calling routine
49  CHARACTER(len=*), INTENT(in),optional :: cd_message !< error message string
50  CHARACTER(len=*), INTENT(in),optional :: file !< file called from
51  INTEGER,INTENT(in),optional :: line !< line in file called from
52  INTEGER,INTENT(in),optional :: rcode !< optional code to return to invoking environment
53 !--------------------------------------------------------------------
54  INTEGER :: ierror, errcode
55  character(len=*),parameter :: subname = '(oasis_abort)'
56 !--------------------------------------------------------------------
57 
58  if (present(id_compid)) &
59  WRITE (nulprt,*) subname,astr,'compid = ',id_compid
60  if (present(cd_routine)) &
61  WRITE (nulprt,*) subname,astr,'called by = ',trim(cd_routine)
62  if (present(cd_message)) &
63  WRITE (nulprt,*) subname,astr,'message = ',trim(cd_message)
64  if (present(file)) &
65  WRITE (nulprt,*) subname,astr,'file = ',trim(file)
66  if (present(line)) &
67  WRITE (nulprt,*) subname,astr,'line = ',line
68  IF (PRESENT(rcode)) THEN
69  errcode=rcode
70  WRITE (nulprt,*) subname,astr,'errcode = ',errcode
71  ELSE
72  errcode=1
73  ENDIF
74 
75  WRITE (nulprt,*) subname,astr,'on model = ',trim(compnm)
76  WRITE (nulprt,*) subname,astr,'on global rank = ',mpi_rank_global
77  WRITE (nulprt,*) subname,astr,'on local rank = ',mpi_rank_local
78  WRITE (nulprt,*) subname,astr,'CALLING ABORT FROM OASIS LAYER NOW'
79  CALL oasis_flush(nulprt)
80 
81 #if defined use_comm_MPI1 || defined use_comm_MPI2
82  CALL mpi_abort (mpi_comm_global, errcode, ierror)
83 #endif
84 
85  stop
86 
87 END SUBROUTINE oasis_abort
88 
89 !==========================================================================
90 
91 !> Flushes output to file
92 
93 SUBROUTINE oasis_flush(nu)
94 
95  IMPLICIT NONE
96 
97 !--------------------------------------------------------------------
98  INTEGER(kind=ip_intwp_p),INTENT(in) :: nu !< unit number of file
99 !--------------------------------------------------------------------
100  character(len=*),parameter :: subname = '(oasis_flush)'
101 !--------------------------------------------------------------------
102 
103  CALL flush(nu)
104 
105 END SUBROUTINE oasis_flush
106 
107 !==========================================================================
108 
109 !> Get a free unit number
110 
111 SUBROUTINE oasis_unitget(uio)
113  IMPLICIT NONE
114 
115 !--------------------------------------------------------------------
116  INTEGER(kind=ip_intwp_p),INTENT(out) :: uio !< unit number
117 !--------------------------------------------------------------------
118  INTEGER(kind=ip_intwp_p) :: n1 ! search for unit number
119  logical :: found,l_open
120  character(len=*),parameter :: subname = '(oasis_unitget)'
121 !--------------------------------------------------------------------
122 
123  ! start at maxion and decrement the unit numbers
124  n1 = maxion+1
125  found = .false.
126  do while (n1 > minion .and. .not.found)
127  n1 = n1 - 1
128  inquire(unit=n1,opened=l_open)
129  if(.not.l_open) found=.true.
130  if (found .and. oasis_debug >= 2) write(nulprt,*) subname,n1
131  enddo
132 
133  if (.not.found) then
134  write(nulprt,*) subname,estr,'no unit number available '
135  write(nulprt,*) subname,estr,'min/max units checked = ',minion,maxion
136  call oasis_abort(file=__file__,line=__line__)
137  endif
138 
139  uio = n1
140 
141 END SUBROUTINE oasis_unitget
142 
143 !==========================================================================
144 
145 !> Set the minimum unit number allowed
146 
147 SUBROUTINE oasis_unitsetmin(uio)
149  IMPLICIT NONE
150 
151 !--------------------------------------------------------------------
152  INTEGER(kind=ip_intwp_p),INTENT(in) :: uio !< unit number
153 !--------------------------------------------------------------------
154  character(len=*),parameter :: subname = '(oasis_unitsetmin)'
155 !--------------------------------------------------------------------
156 
157  minion = uio
158  if (oasis_debug >= 20) write(nulprt,*) subname,minion
159 
160 END SUBROUTINE oasis_unitsetmin
161 
162 !==========================================================================
163 
164 !> Set the maximum unit number allowed
165 
166 SUBROUTINE oasis_unitsetmax(uio)
168  IMPLICIT NONE
169 
170 !--------------------------------------------------------------------
171  INTEGER(kind=ip_intwp_p),INTENT(in) :: uio !< unit number
172 !--------------------------------------------------------------------
173  character(len=*),parameter :: subname = '(oasis_unitsetmax)'
174 !--------------------------------------------------------------------
175 
176  maxion = uio
177  if (oasis_debug >= 20) write(nulprt,*) subname,maxion
178 
179 END SUBROUTINE oasis_unitsetmax
180 
181 !==========================================================================
182 
183 !> Release a unit number for reuse
184 
185 SUBROUTINE oasis_unitfree(uio)
187  IMPLICIT NONE
188 
189 !--------------------------------------------------------------------
190  INTEGER(kind=ip_intwp_p),INTENT(in) :: uio !< unit number
191 !--------------------------------------------------------------------
192  character(len=*),parameter :: subname = '(oasis_unitfree)'
193 !--------------------------------------------------------------------
194 
195 ! tcraig, this is a no-op since we are no longer tracking units
196 ! explicitly. instead, we are searching for free units and using them.
197 ! either a unit number is open or closed and we'll check that explicitly
198 
199  if (oasis_debug >= 20) write(nulprt,*) subname,uio
200 
201 END SUBROUTINE oasis_unitfree
202 
203 !=========================================================================
204 !==========================================================================
205 
206 !> Used when a subroutine is entered, write info to log file at some debug level
207 
208 SUBROUTINE oasis_debug_enter(string)
210  IMPLICIT NONE
211 
212 !--------------------------------------------------------------------
213  CHARACTER(len=*), INTENT(in) :: string !< name of the subroutine
214 
215  character(len=*),parameter :: subname = '(oasis_debug_enter)'
216  CHARACTER(len=1), pointer :: ch_blank(:)
217  CHARACTER(len=500) :: tree_enter
218 
219  if (oasis_debug >= 10) then
220  ALLOCATE (ch_blank(tree_indent))
221  ch_blank='-'
222  tree_enter='-- ENTER '//trim(string)
223  WRITE(nulprt,*) ch_blank,trim(tree_enter)
225  DEALLOCATE (ch_blank)
226  CALL oasis_flush(nulprt)
227  endif
228 
229 END SUBROUTINE oasis_debug_enter
230 
231 !==========================================================================
232 
233 !> Used when a subroutine is exited, write info to log file at some debug level
234 
235 SUBROUTINE oasis_debug_exit(string)
237  IMPLICIT NONE
238 
239 !--------------------------------------------------------------------
240  CHARACTER(len=*), INTENT(in) :: string !< name of subroutine
241 
242  character(len=*),parameter :: subname = '(oasis_debug_exit)'
243  CHARACTER(len=1), pointer :: ch_blank(:)
244  CHARACTER(len=500) :: tree_exit
245 
246  IF (oasis_debug >= 10) THEN
248  ALLOCATE (ch_blank(tree_indent))
249  ch_blank='-'
250  tree_exit='-- EXIT '//trim(string)
251  WRITE(nulprt,*) ch_blank,trim(tree_exit)
252  DEALLOCATE (ch_blank)
253  CALL oasis_flush(nulprt)
254  ENDIF
255 
256 END SUBROUTINE oasis_debug_exit
257 
258 !==========================================================================
259 
260 !> Used to write information from a subroutine, write info to log file at some debug level
261 
262 SUBROUTINE oasis_debug_note(string)
264  IMPLICIT NONE
265 
266 !--------------------------------------------------------------------
267  CHARACTER(len=*), INTENT(in) :: string !< string to write
268 
269  character(len=*),parameter :: subname = '(oasis_debug_note)'
270  CHARACTER(len=1), pointer :: ch_blank(:)
271  CHARACTER(len=500) :: tree_note
272 
273  if (oasis_debug >= 12) then
274  ALLOCATE (ch_blank(tree_indent))
275  ch_blank='-'
276  tree_note='-- NOTE '//trim(string)
277  WRITE(nulprt,*) ch_blank,trim(tree_note)
278  DEALLOCATE(ch_blank)
279  call oasis_flush(nulprt)
280  endif
281 
282 END SUBROUTINE oasis_debug_note
283 
284 !==========================================================================
285 
286 !> Sort a character array and compute a sort key.
287 
288 ! !DESCRIPTION:
289 ! Sort a character array and the associated array(s) based on a
290 ! reasonably fast sort algorithm
291 
292 ! !INTERFACE: -----------------------------------------------------------------
293 
294 subroutine oasis_sys_sortc(num, fld, sortkey)
296 ! !USES:
297 
298  !--- local kinds ---
299  integer,parameter :: R8 = ip_double_p
300  integer,parameter :: IN = ip_i4_p
301  integer,parameter :: CL = ic_lvar
302 
303 ! !INPUT/OUTPUT PARAMETERS:
304 
305  integer(IN), intent(in) :: num !< size of array
306  character(len=CL),intent(inout) :: fld(:) !< sort field
307  integer(IN) ,intent(inout) :: sortkey(:) !< sort key
308 
309 ! !EOP
310 
311  !--- local ---
312  integer(IN) :: n1,n2
313  character(CL), pointer :: tmpfld(:)
314  integer(IN) , pointer :: tmpkey(:)
315 
316  !--- formats ---
317  character(*),parameter :: subName = '(oasis_sys_sortC) '
318 
319 !-------------------------------------------------------------------------------
320 !
321 !-------------------------------------------------------------------------------
322 
323 ! call oasis_debug_enter(subname)
324 
325  allocate(tmpfld((num+1)/2))
326  allocate(tmpkey((num+1)/2))
327  call oasis_sys_mergesortc(num,fld,tmpfld,sortkey,tmpkey)
328  deallocate(tmpfld)
329  deallocate(tmpkey)
330 
331 ! call oasis_debug_exit(subname)
332 
333 end subroutine oasis_sys_sortc
334 
335 !==========================================================================
336 
337 !> Sort a integer array and compute a sort key.
338 
339 ! !DESCRIPTION:
340 ! Sort a character array and the associated array(s) based on a
341 ! reasonably fast sort algorithm
342 
343 ! !INTERFACE: -----------------------------------------------------------------
344 
345 subroutine oasis_sys_sorti(num, fld, sortkey)
347 ! !USES:
348 
349  !--- local kinds ---
350  integer,parameter :: R8 = ip_double_p
351  integer,parameter :: IN = ip_i4_p
352  integer,parameter :: CL = ic_lvar
353 
354 ! !INPUT/OUTPUT PARAMETERS:
355 
356  integer(IN),intent(in) :: num !< size of array
357  integer(IN),intent(inout) :: fld(:) !< sort field
358  integer(IN),intent(inout) :: sortkey(:) !< sort key
359 
360 ! !EOP
361 
362  !--- local ---
363  integer(IN) :: n1,n2
364  integer(IN), pointer :: tmpfld(:)
365  integer(IN), pointer :: tmpkey(:)
366 
367  !--- formats ---
368  character(*),parameter :: subName = '(oasis_sys_sortI) '
369 
370 !-------------------------------------------------------------------------------
371 !
372 !-------------------------------------------------------------------------------
373 
374 ! call oasis_debug_enter(subname)
375 
376  allocate(tmpfld((num+1)/2))
377  allocate(tmpkey((num+1)/2))
378  call oasis_sys_mergesorti(num,fld,tmpfld,sortkey,tmpkey)
379  deallocate(tmpfld)
380  deallocate(tmpkey)
381 
382 ! call oasis_debug_exit(subname)
383 
384 end subroutine oasis_sys_sorti
385 
386 !------------------------------------------------------------
387 
388 !> Sort an integer array using a sort key.
389 
390 ! !DESCRIPTION:
391 ! Rearrange and integer array based on an input sortkey
392 
393 ! !INTERFACE: -----------------------------------------------------------------
394 
395 subroutine oasis_sys_sortikey(num, arr, sortkey)
397 ! !USES:
398 
399  !--- local kinds ---
400  integer,parameter :: R8 = ip_double_p
401  integer,parameter :: IN = ip_i4_p
402  integer,parameter :: CL = ic_lvar
403 
404 ! !INPUT/OUTPUT PARAMETERS:
405 
406  integer(IN),intent(in) :: num !< size of array
407  integer(IN),intent(inout) :: arr(:) !< field to sort
408  integer(IN),intent(in) :: sortkey(:) !< sort key
409 
410 ! !EOP
411 
412  !--- local ---
413  integer(IN) :: n1,n2
414  integer(IN), pointer :: tmparr(:)
415 
416  !--- formats ---
417  character(*),parameter :: subName = '(oasis_sys_sortIkey) '
418 
419 !-------------------------------------------------------------------------------
420 !
421 !-------------------------------------------------------------------------------
422 
423 ! call oasis_debug_enter(subname)
424 
425  if (num /= size(arr) .or. num /= size(sortkey)) then
426  WRITE(nulprt,*) subname,estr,'on size of input arrays :',num,size(arr),size(sortkey)
427  call oasis_abort(file=__file__,line=__line__)
428  endif
429 
430  allocate(tmparr(num))
431  tmparr(1:num) = arr(1:num)
432  do n1 = 1,num
433  arr(n1) = tmparr(sortkey(n1))
434  enddo
435  deallocate(tmparr)
436 
437 ! call oasis_debug_exit(subname)
438 
439 end subroutine oasis_sys_sortikey
440 
441 !==========================================================================
442 !==========================================================================
443 
444 !> Generic oasis_sys_mergesortC routine for character strings
445 
446 recursive subroutine oasis_sys_mergesortc(N,A,T,S,Z)
447 
448  !--- local kinds ---
449  integer,parameter :: R8 = ip_double_p
450  integer,parameter :: IN = ip_i4_p
451  integer,parameter :: CL = ic_lvar
452 
453  integer , intent(in) :: N ! size
454  character(CL), dimension(N) , intent(inout) :: A ! data to sort
455  character(CL), dimension((N+1)/2), intent(out) :: T ! data tmp
456  integer(IN) , dimension(N) , intent(inout) :: S ! sortkey
457  integer(IN) , dimension((N+1)/2), intent(out) :: Z ! sortkey tmp
458 
459  integer :: NA,NB
460  character(CL) :: V
461  integer(IN) :: Y
462  character(*),parameter :: subName = '(oasis_sys_mergesortC) '
463 
464 ! write(nulprt,*) subname//' N = ',N
465 
466  if (n < 2) return
467  if (n == 2) then
468  if (a(1) > a(2)) then
469  v = a(1)
470  y = s(1)
471  a(1) = a(2)
472  s(1) = s(2)
473  a(2) = v
474  s(2) = y
475  endif
476  return
477  endif
478  na=(n+1)/2
479  nb=n-na
480 
481  call oasis_sys_mergesortc(na,a,t,s,z)
482  call oasis_sys_mergesortc(nb,a(na+1),t,s(na+1),z)
483 
484  if (a(na) > a(na+1)) then
485  t(1:na)=a(1:na)
486  z(1:na)=s(1:na)
487  call oasis_sys_mergec(t,z,na,a(na+1),s(na+1),nb,a,s,n)
488  endif
489  return
490 
491 end subroutine oasis_sys_mergesortc
492 
493 !==========================================================================
494 
495 !> Merge routine needed for mergesortC for character strings
496 
497 subroutine oasis_sys_mergec(A,X,NA,B,Y,NB,C,Z,NC)
498 
499  !--- local kinds ---
500  integer,parameter :: R8 = ip_double_p
501  integer,parameter :: IN = ip_i4_p
502  integer,parameter :: CL = ic_lvar
503 
504  integer, intent(in) :: NA,NB,NC ! Normal usage: NA+NB = NC
505  character(CL), intent(inout) :: A(na) ! B overlays C(NA+1:NC)
506  integer(IN) , intent(inout) :: X(na) ! B overlays C(NA+1:NC)
507  character(CL), intent(in) :: B(nb)
508  integer(IN) , intent(in) :: Y(nb)
509  character(CL), intent(inout) :: C(nc)
510  integer(IN) , intent(inout) :: Z(nc)
511 
512  integer :: I,J,K
513  character(*),parameter :: subName = '(oasis_sys_mergeC) '
514 
515 ! write(nulprt,*) subname//' NA,NB,NC = ',NA,NB,NC
516 
517  i = 1; j = 1; k = 1;
518  do while(i <= na .and. j <= nb)
519  if (a(i) <= b(j)) then
520  c(k) = a(i)
521  z(k) = x(i)
522  i = i+1
523  else
524  c(k) = b(j)
525  z(k) = y(j)
526  j = j+1
527  endif
528  k = k + 1
529  enddo
530  do while (i <= na)
531  c(k) = a(i)
532  z(k) = x(i)
533  i = i + 1
534  k = k + 1
535  enddo
536  return
537 
538 end subroutine oasis_sys_mergec
539 
540 !==========================================================================
541 
542 !> Generic oasis_sys_mergesortI routine for an integer array
543 
544 recursive subroutine oasis_sys_mergesorti(N,A,T,S,Z)
545 
546  !--- local kinds ---
547  integer,parameter :: R8 = ip_double_p
548  integer,parameter :: IN = ip_i4_p
549  integer,parameter :: CL = ic_lvar
550 
551  integer , intent(in) :: N ! size
552  integer(IN), dimension(N) , intent(inout) :: A ! data to sort
553  integer(IN), dimension((N+1)/2), intent(out) :: T ! data tmp
554  integer(IN), dimension(N) , intent(inout) :: S ! sortkey
555  integer(IN), dimension((N+1)/2), intent(out) :: Z ! sortkey tmp
556 
557  integer :: NA,NB
558  integer(IN) :: V
559  integer(IN) :: Y
560  character(*),parameter :: subName = '(oasis_sys_mergesortI) '
561 
562 ! write(nulprt,*) subname//' N = ',N
563 
564  if (n < 2) return
565  if (n == 2) then
566  if (a(1) > a(2)) then
567  v = a(1)
568  y = s(1)
569  a(1) = a(2)
570  s(1) = s(2)
571  a(2) = v
572  s(2) = y
573  endif
574  return
575  endif
576  na=(n+1)/2
577  nb=n-na
578 
579  call oasis_sys_mergesorti(na,a,t,s,z)
580  call oasis_sys_mergesorti(nb,a(na+1),t,s(na+1),z)
581 
582  if (a(na) > a(na+1)) then
583  t(1:na)=a(1:na)
584  z(1:na)=s(1:na)
585  call oasis_sys_mergei(t,z,na,a(na+1),s(na+1),nb,a,s,n)
586  endif
587  return
588 
589 end subroutine oasis_sys_mergesorti
590 
591 !==========================================================================
592 
593 !> Merge routine needed for mergesortI for integer array
594 
595 subroutine oasis_sys_mergei(A,X,NA,B,Y,NB,C,Z,NC)
596 
597  !--- local kinds ---
598  integer,parameter :: R8 = ip_double_p
599  integer,parameter :: IN = ip_i4_p
600  integer,parameter :: CL = ic_lvar
601 
602  integer, intent(in) :: NA,NB,NC ! Normal usage: NA+NB = NC
603  integer(IN), intent(inout) :: A(na) ! B overlays C(NA+1:NC)
604  integer(IN), intent(inout) :: X(na) ! B overlays C(NA+1:NC)
605  integer(IN), intent(in) :: B(nb)
606  integer(IN), intent(in) :: Y(nb)
607  integer(IN), intent(inout) :: C(nc)
608  integer(IN), intent(inout) :: Z(nc)
609 
610  integer :: I,J,K
611  character(*),parameter :: subName = '(oasis_sys_mergeI) '
612 
613 ! write(nulprt,*) subname//' NA,NB,NC = ',NA,NB,NC
614 
615  i = 1; j = 1; k = 1;
616  do while(i <= na .and. j <= nb)
617  if (a(i) <= b(j)) then
618  c(k) = a(i)
619  z(k) = x(i)
620  i = i+1
621  else
622  c(k) = b(j)
623  z(k) = y(j)
624  j = j+1
625  endif
626  k = k + 1
627  enddo
628  do while (i <= na)
629  c(k) = a(i)
630  z(k) = x(i)
631  i = i + 1
632  k = k + 1
633  enddo
634  return
635 
636 end subroutine oasis_sys_mergei
637 
638 !==========================================================================
639 
640 END MODULE mod_oasis_sys
System type methods.
subroutine, public oasis_debug_note(string)
Used to write information from a subroutine, write info to log file at some debug level...
character(len= *), parameter, public astr
Provides a common location for several OASIS variables.
integer(ip_intwp_p), save minion
subroutine, public oasis_unitfree(uio)
Release a unit number for reuse.
integer(kind=ip_intwp_p) nulprt
integer(kind=ip_i4_p) mpi_comm_global
integer(ip_intwp_p), parameter tree_delta
subroutine oasis_sys_mergec(A, X, NA, B, Y, NB, C, Z, NC)
Merge routine needed for mergesortC for character strings.
subroutine, public oasis_abort(id_compid, cd_routine, cd_message, file, line, rcode)
OASIS abort method, publically available to users.
integer, parameter ip_i4_p
recursive subroutine oasis_sys_mergesortc(N, A, T, S, Z)
Generic oasis_sys_mergesortC routine for character strings.
integer(kind=ip_i4_p) mpi_rank_local
Defines kinds for OASIS.
integer, parameter ip_double_p
subroutine, public oasis_debug_enter(string)
Used when a subroutine is entered, write info to log file at some debug level.
subroutine, public oasis_sys_sortikey(num, arr, sortkey)
Sort an integer array using a sort key.
integer(kind=ip_i4_p) mpi_rank_global
subroutine, public oasis_sys_sortc(num, fld, sortkey)
Sort a character array and compute a sort key.
subroutine, public oasis_unitsetmin(uio)
Set the minimum unit number allowed.
character(len=ic_lvar) compnm
integer(kind=ip_i4_p) oasis_debug
character(len= *), parameter, public estr
integer, parameter ic_lvar
subroutine, public oasis_unitget(uio)
Get a free unit number.
integer(ip_intwp_p), save tree_indent
subroutine, public oasis_flush(nu)
Flushes output to file.
subroutine, public oasis_sys_sorti(num, fld, sortkey)
Sort a integer array and compute a sort key.
recursive subroutine oasis_sys_mergesorti(N, A, T, S, Z)
Generic oasis_sys_mergesortI routine for an integer array.
integer(ip_intwp_p), save maxion
subroutine oasis_sys_mergei(A, X, NA, B, Y, NB, C, Z, NC)
Merge routine needed for mergesortI for integer array.
subroutine, public oasis_unitsetmax(uio)
Set the maximum unit number allowed.
subroutine, public oasis_debug_exit(string)
Used when a subroutine is exited, write info to log file at some debug level.
character(len= *), parameter, public wstr