mod_oasis_var.F90 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. !> OASIS variable data and methods
  2. MODULE mod_oasis_var
  3. USE mod_oasis_kinds
  4. USE mod_oasis_data
  5. USE mod_oasis_parameters
  6. USE mod_oasis_sys
  7. USE mod_oasis_mpi
  8. USE mod_oasis_timer
  9. USE mod_oasis_part
  10. IMPLICIT none
  11. private
  12. !--- interfaces ---
  13. public oasis_def_var
  14. public oasis_var_setup
  15. !--- datatypes ---
  16. integer(ip_intwp_p),public :: maxvar !< number of potential variables, derived from namcouple input
  17. integer(kind=ip_i4_p),parameter,public :: mvarcpl = 10 !< max namcouples per variable
  18. !> Model variable data for model coupling
  19. type prism_var_type
  20. character(len=ic_lvar):: name !< variable name
  21. integer(kind=ip_i4_p) :: part !< variable partition
  22. integer(kind=ip_i4_p) :: ndim !< rank of variable
  23. integer(kind=ip_i4_p) :: num !< size of variable
  24. integer(kind=ip_i4_p) :: ops !< input or output
  25. integer(kind=ip_i4_p) :: type !< type kind of variable
  26. integer(kind=ip_i4_p) :: size !< total size of field
  27. integer(kind=ip_i4_p) :: ncpl !< number of namcouple couplers
  28. integer(kind=ip_i4_p) :: cpl(mvarcpl) !< list of namcouple couplers
  29. end type prism_var_type
  30. integer(kind=ip_intwp_p),public :: prism_nvar = 0 !< number of variables defined
  31. TYPE(prism_var_type),POINTER,public :: prism_var(:) !< list of defined variables
  32. CONTAINS
  33. !---------------------------------------------------------------
  34. !> The OASIS user interface to define variables
  35. SUBROUTINE oasis_def_var(id_nports, cdport, id_part, &
  36. id_var_nodims, kinout, id_var_shape, ktype, kinfo)
  37. !---------------------------------------------------------------
  38. INTEGER(kind=ip_i4_p),intent(out) :: id_nports !< coupling field ID
  39. CHARACTER(len=*) ,intent(in) :: cdport !< field name as in namcouple
  40. INTEGER(kind=ip_i4_p),intent(in) :: id_part !< partition ID
  41. INTEGER(kind=ip_i4_p),intent(in) :: id_var_nodims(2) !< rank and number of bundles
  42. INTEGER(kind=ip_i4_p),intent(in) :: kinout !< input or output flag
  43. INTEGER(kind=ip_i4_p),intent(in) :: id_var_shape(2*id_var_nodims(1)) !< size of field
  44. INTEGER(kind=ip_i4_p),intent(in) :: ktype !< type of coupling field
  45. INTEGER(kind=ip_i4_p),intent(out),optional :: kinfo !< return code
  46. !---------------------------------------------------------------
  47. INTEGER(kind=ip_i4_p) :: n
  48. CHARACTER(len=ic_lvar) :: trimmed_cdport ! Trimmed version of cdport
  49. character(len=*),parameter :: subname = '(oasis_def_var)'
  50. LOGICAL :: l_field_in_namcouple
  51. !---------------------------------------------------------------
  52. call oasis_debug_enter(subname)
  53. if (.not. oasis_coupled) then
  54. call oasis_debug_exit(subname)
  55. return
  56. endif
  57. !-------------------------------------------------
  58. !> * Check len of incoming variable name
  59. ! Trim incoming name once to avoid multiple trim operations
  60. ! in subsequent loops
  61. !-------------------------------------------------
  62. if (len_trim(cdport) > ic_lvar) then
  63. WRITE(nulprt,*) subname,estr,'variable too long = ',trim(cdport)
  64. WRITE(nulprt,*) subname,estr,'max variable length (ic_lvar) = ',ic_lvar
  65. call oasis_abort()
  66. endif
  67. trimmed_cdport = trim(cdport)
  68. kinfo = OASIS_Ok
  69. l_field_in_namcouple = .FALSE.
  70. n = 0
  71. !-------------------------------------------------
  72. !> * Search for field in namcouple field lists
  73. !-------------------------------------------------
  74. ! If either condition ceases to be true then bail out of the loop
  75. DO WHILE (n < size_namfld .AND. (.NOT.l_field_in_namcouple))
  76. n = n+1
  77. IF ( (trimmed_cdport == total_namsrcfld(n)).OR. &
  78. (trimmed_cdport == total_namdstfld(n)) ) THEN
  79. l_field_in_namcouple = .TRUE.
  80. ENDIF
  81. enddo
  82. !-------------------------------------------------
  83. !> * Return if field not found in namcouple
  84. !-------------------------------------------------
  85. if (.not. l_field_in_namcouple) then
  86. id_nports = OASIS_Var_Uncpl
  87. if (OASIS_debug >= 2) then
  88. write(nulprt,*) subname,' variable not in namcouple return ',trimmed_cdport
  89. call oasis_flush(nulprt)
  90. endif
  91. call oasis_debug_exit(subname)
  92. return
  93. endif
  94. !-------------------------------------------------
  95. !> * Abort if field already defined
  96. !-------------------------------------------------
  97. do n = 1,prism_nvar
  98. if (trimmed_cdport == prism_var(n)%name) then
  99. write(nulprt,*) subname,estr,'variable already defined with def_var = ',trimmed_cdport
  100. write(nulprt,*) subname,estr,'check oasis_def_var calls in your model'
  101. call oasis_abort()
  102. endif
  103. enddo
  104. !-------------------------------------------------
  105. !> * Increment the variable and store the values
  106. !-------------------------------------------------
  107. prism_nvar = prism_nvar + 1
  108. id_nports = prism_nvar
  109. if (prism_nvar > maxvar) then
  110. write(nulprt,*) subname,estr,'prism_nvar too large = ',prism_nvar,maxvar
  111. write(nulprt,*) subname,estr,'check maxvar set in oasis_init_comp'
  112. call oasis_abort()
  113. endif
  114. call oasis_var_zero(prism_var(prism_nvar))
  115. prism_var(prism_nvar)%name = trimmed_cdport
  116. prism_var(prism_nvar)%part = id_part
  117. prism_var(prism_nvar)%ndim = id_var_nodims(1)
  118. prism_var(prism_nvar)%num = id_var_nodims(2)
  119. prism_var(prism_nvar)%ops = kinout
  120. prism_var(prism_nvar)%type = ktype
  121. prism_var(prism_nvar)%size = 1
  122. do n = 1,prism_var(prism_nvar)%ndim
  123. prism_var(prism_nvar)%size = prism_var(prism_nvar)%size*(id_var_shape(2*n)-&
  124. id_var_shape(2*n-1)+1)
  125. enddo
  126. prism_var(prism_nvar)%ncpl = 0
  127. prism_var(prism_nvar)%cpl = 0
  128. !----------------------------------
  129. !> * Write some diagnostics
  130. !----------------------------------
  131. if (OASIS_debug >= 2) then
  132. write(nulprt,*) ' '
  133. write(nulprt,*) subname,' prism_nvar = ',prism_nvar
  134. write(nulprt,*) subname,' varname = ',prism_nvar,trim(prism_var(prism_nvar)%name)
  135. write(nulprt,*) subname,' varpart = ',prism_nvar,prism_var(prism_nvar)%part
  136. write(nulprt,*) subname,' varndim = ',prism_nvar,prism_var(prism_nvar)%ndim
  137. write(nulprt,*) subname,' varnum = ',prism_nvar,prism_var(prism_nvar)%num
  138. write(nulprt,*) subname,' varops = ',prism_nvar,prism_var(prism_nvar)%ops
  139. write(nulprt,*) subname,' vartype = ',prism_nvar,prism_var(prism_nvar)%type
  140. write(nulprt,*) subname,' varsize = ',prism_nvar,prism_var(prism_nvar)%size
  141. write(nulprt,*) ' '
  142. CALL oasis_flush(nulprt)
  143. endif
  144. call oasis_debug_exit(subname)
  145. END SUBROUTINE oasis_def_var
  146. !---------------------------------------------------------------
  147. !> Synchronize variables across all tasks, called at oasis enddef.
  148. SUBROUTINE oasis_var_setup()
  149. IMPLICIT NONE
  150. !--------------------------------------------------------
  151. integer(kind=ip_intwp_p) :: m,n,p,v
  152. INTEGER(kind=ip_intwp_p) :: ierr, taskid
  153. integer(kind=ip_intwp_p) :: vcnt
  154. logical :: found, fastcheckout
  155. character(len=ic_lvar) ,pointer :: vname0(:),vname(:)
  156. character(len=ic_lvar2) ,pointer :: pname0(:),pname(:)
  157. integer(kind=ip_intwp_p),pointer :: inout0(:),inout(:)
  158. logical, parameter :: local_timers_on = .false.
  159. character(len=*),parameter :: subname = '(oasis_var_setup)'
  160. !--------------------------------------------------------
  161. call oasis_debug_enter(subname)
  162. IF (local_timers_on) call oasis_timer_start('var_setup')
  163. IF (local_timers_on) call oasis_timer_start('var_setup_reducelists')
  164. allocate(vname0(prism_nvar))
  165. allocate(pname0(prism_nvar))
  166. allocate(inout0(prism_nvar))
  167. do n = 1,prism_nvar
  168. vname0(n) = prism_var(n)%name
  169. inout0(n) = prism_var(n)%ops
  170. pname0(n) = prism_part(prism_var(n)%part)%partname
  171. enddo
  172. call oasis_mpi_reducelists(vname0,mpi_comm_local,vcnt,vname,'var_setup', &
  173. fastcheck=.true.,fastcheckout=fastcheckout, &
  174. linp2=pname0,lout2=pname,linp3=inout0,lout3=inout)
  175. deallocate(vname0)
  176. deallocate(pname0)
  177. deallocate(inout0)
  178. IF (local_timers_on) call oasis_timer_stop('var_setup_reducelists')
  179. !-------------------------------------------------
  180. !> * Initialize variables on tasks where they are not previously defined.
  181. ! if fastcheck worked, then don't need to do this extra work to add undefined vars
  182. !-------------------------------------------------
  183. if (.not. fastcheckout) then
  184. if (local_timers_on) call oasis_timer_start('var_setup_initvar')
  185. do v = 1,vcnt
  186. !--- either a prism_var that already exists
  187. found = .false.
  188. n = 0
  189. do while (n < prism_nvar .and. .not.found)
  190. n = n + 1
  191. if (prism_var(n)%name == vname(v)) then
  192. found = .true.
  193. endif
  194. enddo
  195. !--- or a new prism_var that must be instantiated
  196. if (.not.found) then
  197. prism_nvar = prism_nvar + 1
  198. call oasis_var_zero(prism_var(prism_nvar))
  199. prism_var(prism_nvar)%name = vname(v)
  200. prism_var(prism_nvar)%ops = inout(v)
  201. prism_var(prism_nvar)%ncpl = 0
  202. !--- figure out the local part id for the part name
  203. p = 0
  204. found = .false.
  205. do while (p < prism_npart .and. .not.found)
  206. p = p + 1
  207. if (prism_part(p)%partname == pname(v)) then
  208. found = .true.
  209. endif
  210. enddo
  211. if (found) then
  212. prism_var(prism_nvar)%part = p
  213. if (OASIS_debug >= 15) then
  214. write(nulprt,*) subname,' found part match ',trim(vname(v)),trim(pname(v)),p
  215. endif
  216. else
  217. write(nulprt,*) subname,estr,'prism part not found part = ',trim(pname(v)),' var = ',trim(vname(v))
  218. call oasis_abort()
  219. endif
  220. if (OASIS_debug >= 2) then
  221. write(nulprt,*) ' '
  222. write(nulprt,*) subname,' add var = ',prism_nvar,trim(prism_var(prism_nvar)%name),&
  223. prism_var(prism_nvar)%part,&
  224. trim(prism_part(prism_var(prism_nvar)%part)%partname),prism_var(prism_nvar)%ops
  225. CALL oasis_flush(nulprt)
  226. ENDIF
  227. endif
  228. enddo ! v = 1,vcnt
  229. if (local_timers_on) call oasis_timer_stop ('var_setup_initvar')
  230. endif ! fastcheckout
  231. deallocate(vname,pname,inout)
  232. IF (local_timers_on) call oasis_timer_stop('var_setup')
  233. call oasis_debug_exit(subname)
  234. END SUBROUTINE oasis_var_setup
  235. !---------------------------------------------------------------
  236. !> Zero variable information
  237. SUBROUTINE oasis_var_zero(prism_var)
  238. IMPLICIT NONE
  239. !--------------------------------------------------------
  240. type(prism_var_type),intent(inout) :: prism_var
  241. character(len=*),parameter :: subname = '(oasis_var_zero)'
  242. !--------------------------------------------------------
  243. call oasis_debug_enter(subname)
  244. prism_var%name = 'oasis_var_name_unset'
  245. prism_var%part = -1
  246. prism_var%ndim = -1
  247. prism_var%num = -1
  248. prism_var%ops = -1
  249. prism_var%type = -1
  250. prism_var%size = -1
  251. prism_var%ncpl = 0
  252. prism_var%cpl = -1
  253. call oasis_debug_exit(subname)
  254. END SUBROUTINE oasis_var_zero
  255. !---------------------------------------------------------------
  256. END MODULE mod_oasis_var