1 | |
---|
2 | !> OASIS variable data and methods |
---|
3 | |
---|
4 | MODULE mod_oasis_var |
---|
5 | |
---|
6 | USE mod_oasis_kinds |
---|
7 | USE mod_oasis_data |
---|
8 | USE mod_oasis_parameters |
---|
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 | !> Overloaded interface into oasis_def_var to support old and new interface |
---|
23 | interface oasis_def_var ; module procedure & |
---|
24 | oasis_def_var_v1, & |
---|
25 | oasis_def_var_v2 |
---|
26 | end interface |
---|
27 | |
---|
28 | !--- datatypes --- |
---|
29 | |
---|
30 | integer(ip_intwp_p),public :: maxvar !< number of potential variables, derived from namcouple input |
---|
31 | integer(kind=ip_i4_p),parameter,public :: mvarcpl = 10 !< max namcouples per variable |
---|
32 | |
---|
33 | !> Model variable data for model coupling |
---|
34 | type prism_var_type |
---|
35 | character(len=ic_lvar):: name !< variable name |
---|
36 | integer(kind=ip_i4_p) :: part !< variable partition |
---|
37 | integer(kind=ip_i4_p) :: ndim !< rank of variable |
---|
38 | integer(kind=ip_i4_p) :: num !< size of variable |
---|
39 | integer(kind=ip_i4_p) :: ops !< input or output |
---|
40 | integer(kind=ip_i4_p) :: type !< type kind of variable |
---|
41 | integer(kind=ip_i4_p) :: size !< total size of field |
---|
42 | integer(kind=ip_i4_p) :: ncpl !< number of namcouple couplers |
---|
43 | integer(kind=ip_i4_p) :: cpl(mvarcpl) !< list of namcouple couplers |
---|
44 | end type prism_var_type |
---|
45 | |
---|
46 | integer(kind=ip_intwp_p),public :: prism_nvar = 0 !< number of variables defined |
---|
47 | TYPE(prism_var_type),POINTER,public :: prism_var(:) !< list of defined variables |
---|
48 | |
---|
49 | CONTAINS |
---|
50 | |
---|
51 | !--------------------------------------------------------------- |
---|
52 | |
---|
53 | !> The original OASIS user interface to define variables |
---|
54 | !> Called via oasis_def_var |
---|
55 | |
---|
56 | SUBROUTINE oasis_def_var_v1(id_nports, cdport, id_part, & |
---|
57 | id_var_nodims, kinout, id_var_shape, ktype, kinfo) |
---|
58 | !--------------------------------------------------------------- |
---|
59 | INTEGER(kind=ip_i4_p),intent(out) :: id_nports !< coupling field ID |
---|
60 | CHARACTER(len=*) ,intent(in) :: cdport !< field name as in namcouple |
---|
61 | INTEGER(kind=ip_i4_p),intent(in) :: id_part !< partition ID |
---|
62 | INTEGER(kind=ip_i4_p),intent(in) :: id_var_nodims(2) !< rank and number of bundles |
---|
63 | INTEGER(kind=ip_i4_p),intent(in) :: kinout !< input or output flag |
---|
64 | INTEGER(kind=ip_i4_p),intent(in) :: id_var_shape(2*id_var_nodims(1)) !< size of field (no longer used) |
---|
65 | INTEGER(kind=ip_i4_p),intent(in) :: ktype !< type of coupling field |
---|
66 | INTEGER(kind=ip_i4_p),intent(out),optional :: kinfo !< return code |
---|
67 | !--------------------------------------------------------------- |
---|
68 | character(len=*),parameter :: subname = '(oasis_def_var_v1)' |
---|
69 | !--------------------------------------------------------------- |
---|
70 | |
---|
71 | call oasis_debug_enter(subname) |
---|
72 | |
---|
73 | if (present(kinfo)) then |
---|
74 | call oasis_def_var_v2(id_nports, cdport, id_part, & |
---|
75 | id_var_nodims, kinout, ktype, kinfo) |
---|
76 | else |
---|
77 | call oasis_def_var_v2(id_nports, cdport, id_part, & |
---|
78 | id_var_nodims, kinout, ktype) |
---|
79 | endif |
---|
80 | |
---|
81 | call oasis_debug_exit(subname) |
---|
82 | |
---|
83 | END SUBROUTINE oasis_def_var_v1 |
---|
84 | |
---|
85 | !--------------------------------------------------------------- |
---|
86 | |
---|
87 | !> The updated OASIS user interface to define variables |
---|
88 | !> Called via oasis_def_var |
---|
89 | |
---|
90 | SUBROUTINE oasis_def_var_v2(id_nports, cdport, id_part, & |
---|
91 | id_var_nodims, kinout, ktype, kinfo) |
---|
92 | !--------------------------------------------------------------- |
---|
93 | INTEGER(kind=ip_i4_p),intent(out) :: id_nports !< coupling field ID |
---|
94 | CHARACTER(len=*) ,intent(in) :: cdport !< field name as in namcouple |
---|
95 | INTEGER(kind=ip_i4_p),intent(in) :: id_part !< partition ID |
---|
96 | INTEGER(kind=ip_i4_p),intent(in) :: id_var_nodims(2) !< rank and number of bundles |
---|
97 | INTEGER(kind=ip_i4_p),intent(in) :: kinout !< input or output flag |
---|
98 | INTEGER(kind=ip_i4_p),intent(in) :: ktype !< type of coupling field |
---|
99 | INTEGER(kind=ip_i4_p),intent(out),optional :: kinfo !< return code |
---|
100 | !--------------------------------------------------------------- |
---|
101 | INTEGER(kind=ip_i4_p) :: il_var_nodims_temp(2) !< rank and number of bundles temporary |
---|
102 | INTEGER(kind=ip_i4_p) :: n |
---|
103 | CHARACTER(len=ic_lvar) :: trimmed_cdport ! Trimmed version of cdport |
---|
104 | character(len=*),parameter :: subname = '(oasis_def_var_v2)' |
---|
105 | character(len=*),parameter :: subnamei = '(oasis_def_var)' |
---|
106 | LOGICAL :: l_field_in_namcouple |
---|
107 | !--------------------------------------------------------------- |
---|
108 | |
---|
109 | call oasis_debug_enter(subname) |
---|
110 | if (.not. oasis_coupled) then |
---|
111 | call oasis_debug_exit(subname) |
---|
112 | return |
---|
113 | endif |
---|
114 | |
---|
115 | !------------------------------------------------- |
---|
116 | !> * Check len of incoming variable name |
---|
117 | ! Trim incoming name once to avoid multiple trim operations |
---|
118 | ! in subsequent loops |
---|
119 | !------------------------------------------------- |
---|
120 | |
---|
121 | if (len_trim(cdport) > ic_lvar) then |
---|
122 | WRITE(nulprt,*) subnamei,estr,'variable too long = ',trim(cdport) |
---|
123 | WRITE(nulprt,*) subnamei,estr,'max variable length (ic_lvar) = ',ic_lvar |
---|
124 | call oasis_abort(file=__FILE__,line=__LINE__) |
---|
125 | endif |
---|
126 | trimmed_cdport = trim(cdport) |
---|
127 | |
---|
128 | if (present(kinfo)) kinfo = OASIS_Ok |
---|
129 | |
---|
130 | l_field_in_namcouple = .FALSE. |
---|
131 | n = 0 |
---|
132 | |
---|
133 | !------------------------------------------------- |
---|
134 | !> * Search for field in namcouple field lists |
---|
135 | !------------------------------------------------- |
---|
136 | |
---|
137 | ! If either condition ceases to be true then bail out of the loop |
---|
138 | DO WHILE (n < size_namfld .AND. (.NOT.l_field_in_namcouple)) |
---|
139 | n = n+1 |
---|
140 | IF ( (trimmed_cdport == total_namsrcfld(n)).OR. & |
---|
141 | (trimmed_cdport == total_namdstfld(n)) ) THEN |
---|
142 | l_field_in_namcouple = .TRUE. |
---|
143 | ENDIF |
---|
144 | enddo |
---|
145 | |
---|
146 | !------------------------------------------------- |
---|
147 | !> * Return if field not found in namcouple |
---|
148 | !------------------------------------------------- |
---|
149 | |
---|
150 | if (.not. l_field_in_namcouple) then |
---|
151 | id_nports = OASIS_Var_Uncpl |
---|
152 | if (OASIS_debug >= 2) then |
---|
153 | write(nulprt,*) subnamei,' variable not in namcouple return ',trimmed_cdport |
---|
154 | call oasis_flush(nulprt) |
---|
155 | endif |
---|
156 | call oasis_debug_exit(subname) |
---|
157 | return |
---|
158 | endif |
---|
159 | |
---|
160 | !------------------------------------------------- |
---|
161 | !> * Abort if field already defined |
---|
162 | !------------------------------------------------- |
---|
163 | |
---|
164 | do n = 1,prism_nvar |
---|
165 | if (trimmed_cdport == prism_var(n)%name) then |
---|
166 | write(nulprt,*) subnamei,estr,'variable already defined with def_var = ',trimmed_cdport |
---|
167 | write(nulprt,*) subnamei,estr,'check oasis_def_var calls in your model' |
---|
168 | call oasis_abort(file=__FILE__,line=__LINE__) |
---|
169 | endif |
---|
170 | enddo |
---|
171 | |
---|
172 | ! tcraig, this is due to i3.3 in the 2d->1d field bundle renaming |
---|
173 | il_var_nodims_temp(:)=id_var_nodims(:) |
---|
174 | IF (il_var_nodims_temp(2) > 999) THEN |
---|
175 | write(nulprt,*) subnamei,estr,'variable id_var_nodims(2) too large. limit is 999 ',il_var_nodims_temp(2) |
---|
176 | write(nulprt,*) subnamei,estr,'check oasis_def_var calls in your model' |
---|
177 | call oasis_abort(file=__FILE__,line=__LINE__) |
---|
178 | ENDIF |
---|
179 | |
---|
180 | IF (il_var_nodims_temp(2) <= 0) THEN |
---|
181 | il_var_nodims_temp(2)=1 |
---|
182 | WRITE(nulprt,*) subnamei,'WARNING id_var_nodim(2) cannot be negative or 0 ; put to 1' |
---|
183 | call oasis_flush(nulprt) |
---|
184 | ENDIF |
---|
185 | |
---|
186 | !------------------------------------------------- |
---|
187 | !> * Increment the variable and store the values |
---|
188 | !------------------------------------------------- |
---|
189 | |
---|
190 | prism_nvar = prism_nvar + 1 |
---|
191 | id_nports = prism_nvar |
---|
192 | |
---|
193 | if (prism_nvar > maxvar) then |
---|
194 | write(nulprt,*) subnamei,estr,'prism_nvar too large = ',prism_nvar,maxvar |
---|
195 | write(nulprt,*) subnamei,estr,'check maxvar set in oasis_init_comp' |
---|
196 | call oasis_abort(file=__FILE__,line=__LINE__) |
---|
197 | endif |
---|
198 | |
---|
199 | call oasis_var_zero(prism_var(prism_nvar)) |
---|
200 | prism_var(prism_nvar)%name = trimmed_cdport |
---|
201 | prism_var(prism_nvar)%part = id_part |
---|
202 | prism_var(prism_nvar)%num = il_var_nodims_temp(2) |
---|
203 | prism_var(prism_nvar)%ops = kinout |
---|
204 | prism_var(prism_nvar)%type = ktype |
---|
205 | prism_var(prism_nvar)%size = 1 |
---|
206 | prism_var(prism_nvar)%ncpl = 0 |
---|
207 | prism_var(prism_nvar)%cpl = 0 |
---|
208 | |
---|
209 | !---------------------------------- |
---|
210 | !> * Write some diagnostics |
---|
211 | !---------------------------------- |
---|
212 | |
---|
213 | if (OASIS_debug >= 2) then |
---|
214 | write(nulprt,*) ' ' |
---|
215 | write(nulprt,*) subnamei,' prism_nvar = ',prism_nvar |
---|
216 | write(nulprt,*) subnamei,' varname = ',prism_nvar,trim(prism_var(prism_nvar)%name) |
---|
217 | write(nulprt,*) subnamei,' varpart = ',prism_nvar,prism_var(prism_nvar)%part |
---|
218 | write(nulprt,*) subnamei,' varnum = ',prism_nvar,prism_var(prism_nvar)%num |
---|
219 | write(nulprt,*) subnamei,' varops = ',prism_nvar,prism_var(prism_nvar)%ops |
---|
220 | write(nulprt,*) subnamei,' vartype = ',prism_nvar,prism_var(prism_nvar)%type |
---|
221 | write(nulprt,*) ' ' |
---|
222 | CALL oasis_flush(nulprt) |
---|
223 | endif |
---|
224 | |
---|
225 | call oasis_debug_exit(subname) |
---|
226 | |
---|
227 | END SUBROUTINE oasis_def_var_v2 |
---|
228 | |
---|
229 | !--------------------------------------------------------------- |
---|
230 | |
---|
231 | !> Synchronize variables across all tasks, called at oasis enddef. |
---|
232 | |
---|
233 | SUBROUTINE oasis_var_setup() |
---|
234 | IMPLICIT NONE |
---|
235 | |
---|
236 | !-------------------------------------------------------- |
---|
237 | integer(kind=ip_intwp_p) :: m,n,p,v |
---|
238 | INTEGER(kind=ip_intwp_p) :: ierr, taskid |
---|
239 | integer(kind=ip_intwp_p) :: vcnt |
---|
240 | logical :: found, fastcheckout |
---|
241 | character(len=ic_lvar) ,allocatable :: vname0(:),vname(:) |
---|
242 | character(len=ic_lvar2) ,allocatable :: pname0(:),pname(:) |
---|
243 | integer(kind=ip_intwp_p),allocatable :: inout0(:),inout(:) |
---|
244 | integer(kind=ip_intwp_p),allocatable :: vanum0(:),vanum(:) |
---|
245 | logical, parameter :: local_timers_on = .false. |
---|
246 | character(len=*),parameter :: subname = '(oasis_var_setup)' |
---|
247 | !-------------------------------------------------------- |
---|
248 | |
---|
249 | call oasis_debug_enter(subname) |
---|
250 | |
---|
251 | IF (local_timers_on) call oasis_timer_start('var_setup') |
---|
252 | |
---|
253 | IF (local_timers_on) call oasis_timer_start('var_setup_reducelists') |
---|
254 | allocate(vname0(prism_nvar)) |
---|
255 | allocate(pname0(prism_nvar)) |
---|
256 | allocate(inout0(prism_nvar)) |
---|
257 | allocate(vanum0(prism_nvar)) |
---|
258 | do n = 1,prism_nvar |
---|
259 | vname0(n) = prism_var(n)%name |
---|
260 | inout0(n) = prism_var(n)%ops |
---|
261 | vanum0(n) = prism_var(n)%num |
---|
262 | pname0(n) = prism_part(prism_var(n)%part)%partname |
---|
263 | enddo |
---|
264 | |
---|
265 | call oasis_mpi_reducelists(vname0,mpi_comm_local,vcnt,vname,'var_setup', & |
---|
266 | fastcheck=.true.,fastcheckout=fastcheckout, & |
---|
267 | linp2=pname0,lout2=pname,linp3=inout0,lout3=inout,linp4=vanum0,lout4=vanum) |
---|
268 | |
---|
269 | deallocate(vname0) |
---|
270 | deallocate(pname0) |
---|
271 | deallocate(inout0) |
---|
272 | deallocate(vanum0) |
---|
273 | IF (local_timers_on) call oasis_timer_stop('var_setup_reducelists') |
---|
274 | |
---|
275 | !------------------------------------------------- |
---|
276 | !> * Initialize variables on tasks where they are not previously defined. |
---|
277 | ! if fastcheck worked, then don't need to do this extra work to add undefined vars |
---|
278 | !------------------------------------------------- |
---|
279 | |
---|
280 | if (.not. fastcheckout) then |
---|
281 | |
---|
282 | if (local_timers_on) call oasis_timer_start('var_setup_initvar') |
---|
283 | do v = 1,vcnt |
---|
284 | |
---|
285 | !--- either a prism_var that already exists |
---|
286 | found = .false. |
---|
287 | n = 0 |
---|
288 | do while (n < prism_nvar .and. .not.found) |
---|
289 | n = n + 1 |
---|
290 | if (prism_var(n)%name == vname(v)) then |
---|
291 | found = .true. |
---|
292 | endif |
---|
293 | enddo |
---|
294 | |
---|
295 | !--- or a new prism_var that must be instantiated |
---|
296 | if (.not.found) then |
---|
297 | prism_nvar = prism_nvar + 1 |
---|
298 | |
---|
299 | call oasis_var_zero(prism_var(prism_nvar)) |
---|
300 | prism_var(prism_nvar)%name = vname(v) |
---|
301 | prism_var(prism_nvar)%ops = inout(v) |
---|
302 | prism_var(prism_nvar)%num = vanum(v) |
---|
303 | prism_var(prism_nvar)%ncpl = 0 |
---|
304 | !--- figure out the local part id for the part name |
---|
305 | p = 0 |
---|
306 | found = .false. |
---|
307 | do while (p < prism_npart .and. .not.found) |
---|
308 | p = p + 1 |
---|
309 | if (prism_part(p)%partname == pname(v)) then |
---|
310 | found = .true. |
---|
311 | endif |
---|
312 | enddo |
---|
313 | if (found) then |
---|
314 | prism_var(prism_nvar)%part = p |
---|
315 | if (OASIS_debug >= 15) then |
---|
316 | write(nulprt,*) subname,' found part match ',trim(vname(v)),trim(pname(v)),p |
---|
317 | endif |
---|
318 | else |
---|
319 | write(nulprt,*) subname,estr,'prism part not found part = ',trim(pname(v)),' var = ',trim(vname(v)) |
---|
320 | call oasis_abort(file=__FILE__,line=__LINE__) |
---|
321 | endif |
---|
322 | |
---|
323 | if (OASIS_debug >= 2) then |
---|
324 | write(nulprt,*) ' ' |
---|
325 | write(nulprt,*) subname,' add var = ',prism_nvar,trim(prism_var(prism_nvar)%name),& |
---|
326 | prism_var(prism_nvar)%part,& |
---|
327 | trim(prism_part(prism_var(prism_nvar)%part)%partname),prism_var(prism_nvar)%ops |
---|
328 | CALL oasis_flush(nulprt) |
---|
329 | ENDIF |
---|
330 | endif |
---|
331 | |
---|
332 | enddo ! v = 1,vcnt |
---|
333 | if (local_timers_on) call oasis_timer_stop ('var_setup_initvar') |
---|
334 | |
---|
335 | endif ! fastcheckout |
---|
336 | |
---|
337 | deallocate(vname,pname,inout,vanum) |
---|
338 | |
---|
339 | IF (local_timers_on) call oasis_timer_stop('var_setup') |
---|
340 | |
---|
341 | call oasis_debug_exit(subname) |
---|
342 | |
---|
343 | END SUBROUTINE oasis_var_setup |
---|
344 | |
---|
345 | !--------------------------------------------------------------- |
---|
346 | |
---|
347 | !> Zero variable information |
---|
348 | |
---|
349 | SUBROUTINE oasis_var_zero(prism_var) |
---|
350 | IMPLICIT NONE |
---|
351 | |
---|
352 | !-------------------------------------------------------- |
---|
353 | type(prism_var_type),intent(inout) :: prism_var |
---|
354 | character(len=*),parameter :: subname = '(oasis_var_zero)' |
---|
355 | !-------------------------------------------------------- |
---|
356 | |
---|
357 | call oasis_debug_enter(subname) |
---|
358 | |
---|
359 | prism_var%name = 'oasis_var_name_unset' |
---|
360 | prism_var%part = -1 |
---|
361 | prism_var%ndim = -1 |
---|
362 | prism_var%num = -1 |
---|
363 | prism_var%ops = -1 |
---|
364 | prism_var%type = -1 |
---|
365 | prism_var%size = -1 |
---|
366 | prism_var%ncpl = 0 |
---|
367 | prism_var%cpl = -1 |
---|
368 | |
---|
369 | call oasis_debug_exit(subname) |
---|
370 | |
---|
371 | END SUBROUTINE oasis_var_zero |
---|
372 | |
---|
373 | !--------------------------------------------------------------- |
---|
374 | END MODULE mod_oasis_var |
---|
375 | |
---|