Oasis3-MCT
mod_oasis_var.F90
Go to the documentation of this file.
1 
2 !> OASIS variable data and methods
3 
4  MODULE mod_oasis_var
5 
9  USE mod_oasis_sys
10  USE mod_oasis_mpi
11  USE mod_oasis_timer
12  USE mod_oasis_part
13 
14  IMPLICIT none
15 
16  private
17 
18  !--- interfaces ---
19  public oasis_def_var
20  public oasis_var_setup
21 
22  !--- datatypes ---
23 
24  integer(ip_intwp_p),public :: maxvar !< number of potential variables, derived from namcouple input
25  integer(kind=ip_i4_p),parameter,public :: mvarcpl = 10 !< max namcouples per variable
26 
27  !> Model variable data for model coupling
29  character(len=ic_lvar):: name !< variable name
30  integer(kind=ip_i4_p) :: part !< variable partition
31  integer(kind=ip_i4_p) :: ndim !< rank of variable
32  integer(kind=ip_i4_p) :: num !< size of variable
33  integer(kind=ip_i4_p) :: ops !< input or output
34  integer(kind=ip_i4_p) :: type !< type kind of variable
35  integer(kind=ip_i4_p) :: size !< total size of field
36  integer(kind=ip_i4_p) :: ncpl !< number of namcouple couplers
37  integer(kind=ip_i4_p) :: cpl(mvarcpl) !< list of namcouple couplers
38  end type prism_var_type
39 
40  integer(kind=ip_intwp_p),public :: prism_nvar = 0 !< number of variables defined
41  TYPE(prism_var_type),POINTER,public :: prism_var(:) !< list of defined variables
42 
43  CONTAINS
44 
45 !---------------------------------------------------------------
46 
47 !> The OASIS user interface to define variables
48 
49  SUBROUTINE oasis_def_var(id_nports, cdport, id_part, &
50  id_var_nodims, kinout, id_var_shape, ktype, kinfo)
51  !---------------------------------------------------------------
52  INTEGER(kind=ip_i4_p),intent(out) :: id_nports !< coupling field ID
53  CHARACTER(len=*) ,intent(in) :: cdport !< field name as in namcouple
54  INTEGER(kind=ip_i4_p),intent(in) :: id_part !< partition ID
55  INTEGER(kind=ip_i4_p),intent(in) :: id_var_nodims(2) !< rank and number of bundles
56  INTEGER(kind=ip_i4_p),intent(in) :: kinout !< input or output flag
57  INTEGER(kind=ip_i4_p),intent(in) :: id_var_shape(:) !< size of field
58  INTEGER(kind=ip_i4_p),intent(in) :: ktype !< type of coupling field
59  INTEGER(kind=ip_i4_p),intent(out),optional :: kinfo !< return code
60  !---------------------------------------------------------------
61  INTEGER(kind=ip_i4_p) :: n
62  CHARACTER(len=ic_lvar) :: trimmed_cdport ! Trimmed version of cdport
63  character(len=*),parameter :: subname = '(oasis_def_var)'
64  LOGICAL :: l_field_in_namcouple
65  !---------------------------------------------------------------
66 
67  call oasis_debug_enter(subname)
68  if (.not. oasis_coupled) then
69  call oasis_debug_exit(subname)
70  return
71  endif
72 
73  !-------------------------------------------------
74  !> * Check len of incoming variable name
75  ! Trim incoming name once to avoid multiple trim operations
76  ! in subsequent loops
77  !-------------------------------------------------
78 
79  if (len_trim(cdport) > ic_lvar) then
80  WRITE(nulprt,*) subname,estr,'variable too long = ',trim(cdport)
81  WRITE(nulprt,*) subname,estr,'max variable length (ic_lvar) = ',ic_lvar
82  call oasis_abort(file=__file__,line=__line__)
83  endif
84  trimmed_cdport = trim(cdport)
85 
86  kinfo = oasis_ok
87 
88  l_field_in_namcouple = .false.
89  n = 0
90 
91  !-------------------------------------------------
92  !> * Search for field in namcouple field lists
93  !-------------------------------------------------
94 
95  ! If either condition ceases to be true then bail out of the loop
96  DO WHILE (n < size_namfld .AND. (.NOT.l_field_in_namcouple))
97  n = n+1
98  IF ( (trimmed_cdport == total_namsrcfld(n)).OR. &
99  (trimmed_cdport == total_namdstfld(n)) ) THEN
100  l_field_in_namcouple = .true.
101  ENDIF
102  enddo
103 
104  !-------------------------------------------------
105  !> * Return if field not found in namcouple
106  !-------------------------------------------------
107 
108  if (.not. l_field_in_namcouple) then
109  id_nports = oasis_var_uncpl
110  if (oasis_debug >= 2) then
111  write(nulprt,*) subname,' variable not in namcouple return ',trimmed_cdport
112  call oasis_flush(nulprt)
113  endif
114  call oasis_debug_exit(subname)
115  return
116  endif
117 
118  !-------------------------------------------------
119  !> * Abort if field already defined
120  !-------------------------------------------------
121 
122  do n = 1,prism_nvar
123  if (trimmed_cdport == prism_var(n)%name) then
124  write(nulprt,*) subname,estr,'variable already defined with def_var = ',trimmed_cdport
125  write(nulprt,*) subname,estr,'check oasis_def_var calls in your model'
126  call oasis_abort(file=__file__,line=__line__)
127  endif
128  enddo
129 
130  ! tcraig, this is due to i3.3 in the 2d->1d field bundle renaming
131  if (id_var_nodims(2) > 999) then
132  write(nulprt,*) subname,estr,'variable id_var_nodims2 too large. limit is 999 ',id_var_nodims(2)
133  write(nulprt,*) subname,estr,'check oasis_def_var calls in your model'
134  call oasis_abort(file=__file__,line=__line__)
135  endif
136 
137  !-------------------------------------------------
138  !> * Increment the variable and store the values
139  !-------------------------------------------------
140 
141  prism_nvar = prism_nvar + 1
142  id_nports = prism_nvar
143 
144  if (prism_nvar > maxvar) then
145  write(nulprt,*) subname,estr,'prism_nvar too large = ',prism_nvar,maxvar
146  write(nulprt,*) subname,estr,'check maxvar set in oasis_init_comp'
147  call oasis_abort(file=__file__,line=__line__)
148  endif
149 
151  prism_var(prism_nvar)%name = trimmed_cdport
152  prism_var(prism_nvar)%part = id_part
153  prism_var(prism_nvar)%num = id_var_nodims(2)
154  prism_var(prism_nvar)%ops = kinout
155  prism_var(prism_nvar)%type = ktype
156  prism_var(prism_nvar)%size = 1
157  prism_var(prism_nvar)%ncpl = 0
158  prism_var(prism_nvar)%cpl = 0
159 
160  !----------------------------------
161  !> * Write some diagnostics
162  !----------------------------------
163 
164  if (oasis_debug >= 2) then
165  write(nulprt,*) ' '
166  write(nulprt,*) subname,' prism_nvar = ',prism_nvar
167  write(nulprt,*) subname,' varname = ',prism_nvar,trim(prism_var(prism_nvar)%name)
168  write(nulprt,*) subname,' varpart = ',prism_nvar,prism_var(prism_nvar)%part
169  write(nulprt,*) subname,' varnum = ',prism_nvar,prism_var(prism_nvar)%num
170  write(nulprt,*) subname,' varops = ',prism_nvar,prism_var(prism_nvar)%ops
171  write(nulprt,*) subname,' vartype = ',prism_nvar,prism_var(prism_nvar)%type
172  write(nulprt,*) ' '
173  CALL oasis_flush(nulprt)
174  endif
175 
176  call oasis_debug_exit(subname)
177 
178  END SUBROUTINE oasis_def_var
179 
180 !---------------------------------------------------------------
181 
182 !> Synchronize variables across all tasks, called at oasis enddef.
183 
184  SUBROUTINE oasis_var_setup()
185  IMPLICIT NONE
186 
187  !--------------------------------------------------------
188  integer(kind=ip_intwp_p) :: m,n,p,v
189  INTEGER(kind=ip_intwp_p) :: ierr, taskid
190  integer(kind=ip_intwp_p) :: vcnt
191  logical :: found, fastcheckout
192  character(len=ic_lvar) ,pointer :: vname0(:),vname(:)
193  character(len=ic_lvar2) ,pointer :: pname0(:),pname(:)
194  integer(kind=ip_intwp_p),pointer :: inout0(:),inout(:)
195  integer(kind=ip_intwp_p),pointer :: vanum0(:),vanum(:)
196  logical, parameter :: local_timers_on = .false.
197  character(len=*),parameter :: subname = '(oasis_var_setup)'
198  !--------------------------------------------------------
199 
200  call oasis_debug_enter(subname)
201 
202  IF (local_timers_on) call oasis_timer_start('var_setup')
203 
204  IF (local_timers_on) call oasis_timer_start('var_setup_reducelists')
205  allocate(vname0(prism_nvar))
206  allocate(pname0(prism_nvar))
207  allocate(inout0(prism_nvar))
208  allocate(vanum0(prism_nvar))
209  do n = 1,prism_nvar
210  vname0(n) = prism_var(n)%name
211  inout0(n) = prism_var(n)%ops
212  vanum0(n) = prism_var(n)%num
213  pname0(n) = prism_part(prism_var(n)%part)%partname
214  enddo
215 
216  call oasis_mpi_reducelists(vname0,mpi_comm_local,vcnt,vname,'var_setup', &
217  fastcheck=.true.,fastcheckout=fastcheckout, &
218  linp2=pname0,lout2=pname,linp3=inout0,lout3=inout,linp4=vanum0,lout4=vanum)
219 
220  deallocate(vname0)
221  deallocate(pname0)
222  deallocate(inout0)
223  deallocate(vanum0)
224  IF (local_timers_on) call oasis_timer_stop('var_setup_reducelists')
225 
226  !-------------------------------------------------
227  !> * Initialize variables on tasks where they are not previously defined.
228  ! if fastcheck worked, then don't need to do this extra work to add undefined vars
229  !-------------------------------------------------
230 
231  if (.not. fastcheckout) then
232 
233  if (local_timers_on) call oasis_timer_start('var_setup_initvar')
234  do v = 1,vcnt
235 
236  !--- either a prism_var that already exists
237  found = .false.
238  n = 0
239  do while (n < prism_nvar .and. .not.found)
240  n = n + 1
241  if (prism_var(n)%name == vname(v)) then
242  found = .true.
243  endif
244  enddo
245 
246  !--- or a new prism_var that must be instantiated
247  if (.not.found) then
248  prism_nvar = prism_nvar + 1
249 
251  prism_var(prism_nvar)%name = vname(v)
252  prism_var(prism_nvar)%ops = inout(v)
253  prism_var(prism_nvar)%num = vanum(v)
254  prism_var(prism_nvar)%ncpl = 0
255  !--- figure out the local part id for the part name
256  p = 0
257  found = .false.
258  do while (p < prism_npart .and. .not.found)
259  p = p + 1
260  if (prism_part(p)%partname == pname(v)) then
261  found = .true.
262  endif
263  enddo
264  if (found) then
265  prism_var(prism_nvar)%part = p
266  if (oasis_debug >= 15) then
267  write(nulprt,*) subname,' found part match ',trim(vname(v)),trim(pname(v)),p
268  endif
269  else
270  write(nulprt,*) subname,estr,'prism part not found part = ',trim(pname(v)),' var = ',trim(vname(v))
271  call oasis_abort(file=__file__,line=__line__)
272  endif
273 
274  if (oasis_debug >= 2) then
275  write(nulprt,*) ' '
276  write(nulprt,*) subname,' add var = ',prism_nvar,trim(prism_var(prism_nvar)%name),&
277  prism_var(prism_nvar)%part,&
278  trim(prism_part(prism_var(prism_nvar)%part)%partname),prism_var(prism_nvar)%ops
279  CALL oasis_flush(nulprt)
280  ENDIF
281  endif
282 
283  enddo ! v = 1,vcnt
284  if (local_timers_on) call oasis_timer_stop ('var_setup_initvar')
285 
286  endif ! fastcheckout
287 
288  deallocate(vname,pname,inout,vanum)
289 
290  IF (local_timers_on) call oasis_timer_stop('var_setup')
291 
292  call oasis_debug_exit(subname)
293 
294  END SUBROUTINE oasis_var_setup
295 
296 !---------------------------------------------------------------
297 
298 !> Zero variable information
299 
300  SUBROUTINE oasis_var_zero(prism_var)
301  IMPLICIT NONE
302 
303  !--------------------------------------------------------
304  type(prism_var_type),intent(inout) :: prism_var
305  character(len=*),parameter :: subname = '(oasis_var_zero)'
306  !--------------------------------------------------------
307 
308  call oasis_debug_enter(subname)
309 
310  prism_var%name = 'oasis_var_name_unset'
311  prism_var%part = -1
312  prism_var%ndim = -1
313  prism_var%num = -1
314  prism_var%ops = -1
315  prism_var%type = -1
316  prism_var%size = -1
317  prism_var%ncpl = 0
318  prism_var%cpl = -1
319 
320  call oasis_debug_exit(subname)
321 
322  END SUBROUTINE oasis_var_zero
323 
324 !---------------------------------------------------------------
325  END MODULE mod_oasis_var
326 
System type methods.
Provides a common location for several OASIS variables.
integer(kind=ip_intwp_p), parameter oasis_ok
type(prism_part_type), dimension(mpart), public prism_part
list of defined partitions
integer(kind=ip_i4_p) size_namfld
integer(kind=ip_intwp_p) nulprt
subroutine, public oasis_def_var(id_nports, cdport, id_part, id_var_nodims, kinout, id_var_shape, ktype, kinfo)
The OASIS user interface to define variables.
subroutine, public oasis_abort(id_compid, cd_routine, cd_message, file, line, rcode)
OASIS abort method, publically available to users.
Defines kinds for OASIS.
Provides a generic and simpler interface into MPI calls for OASIS.
character(len=ic_lvar), dimension(:), pointer total_namsrcfld
subroutine, public oasis_debug_enter(string)
Used when a subroutine is entered, write info to log file at some debug level.
subroutine, public oasis_mpi_reducelists(linp1, comm, cntout, lout1, callstr, fastcheck, fastcheckout, linp2, lout2, spval2, linp3, lout3, spval3, linp4, lout4, spval4)
Custom method for reducing MPI lists across pes for OASIS.
OASIS partition data and methods.
Defines parameters for OASIS.
character(len=ic_lvar), dimension(:), pointer total_namdstfld
OASIS variable data and methods.
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, parameter ic_lvar
integer(kind=ip_i4_p), parameter, public mvarcpl
max namcouples per variable
integer(kind=ip_intwp_p), parameter oasis_var_uncpl
integer(kind=ip_intwp_p), public prism_npart
number of partitions defined
subroutine, public oasis_flush(nu)
Flushes output to file.
integer(kind=ip_intwp_p), public prism_nvar
number of variables defined
subroutine oasis_var_zero(prism_var)
Zero variable information.
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
Model variable data for model coupling.
subroutine, public oasis_debug_exit(string)
Used when a subroutine is exited, write info to log file at some debug level.