FV3-JEDI
fv3jedi_field_mod.f90
Go to the documentation of this file.
1 ! (C) Copyright 2017-2020 UCAR
2 !
3 ! This software is licensed under the terms of the Apache Licence Version 2.0
4 ! which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
5 
7 
8 ! fckit
9 use fckit_mpi_module
10 
11 ! oops
12 use datetime_mod
13 use oops_variables_mod
14 
15 ! fv3jedi
17 
18 implicit none
19 private
22 
23 ! These are the same methods as used in fv3jedi_fields but with argument being a list of individual
24 ! fields instead of the fv3jedi_fields class
25 interface get_field
26  module procedure get_field_return_type_pointer
27  module procedure get_field_return_array_pointer
28  module procedure get_field_return_array_allocatable
29 end interface
30 
31 integer, parameter, public :: field_clen = 2048
32 
33 ! --------------------------------------------------------------------------------------------------
34 
35 !Field type (individual field)
37  logical :: lalloc = .false.
38  character(len=field_clen) :: short_name = "null" !Short name (to match file name)
39  character(len=field_clen) :: fv3jedi_name = "null" !Common name
40  character(len=field_clen) :: long_name = "null" !More descriptive name
41  character(len=field_clen) :: units = "null" !Units for the field
42  character(len=field_clen) :: io_file = "null" !Which restart to read/write if not the default
43  logical :: tracer = .false. !Whether field is classified as tracer (pos. def.)
44  character(len=field_clen) :: space !One of vector, magnitude, direction
45  character(len=field_clen) :: staggerloc !One of center, eastwest, northsouth, corner
46  integer :: isc, iec, jsc, jec, npz
47  real(kind=kind_real), allocatable :: array(:,:,:)
48  logical :: integerfield = .false.
49 endtype fv3jedi_field
50 
51 ! --------------------------------------------------------------------------------------------------
52 
53 contains
54 
55 ! --------------------------------------------------------------------------------------------------
56 
57 logical function has_field(fields, field_name, field_index)
58 
59 type(fv3jedi_field), intent(in) :: fields(:)
60 character(len=*), intent(in) :: field_name
61 integer, optional, intent(out) :: field_index
62 
63 integer :: var
64 
65 has_field = .false.
66 do var = 1, size(fields)
67  if ( trim(fields(var)%fv3jedi_name) == trim(field_name)) then
68  has_field = .true.
69  if (present(field_index)) field_index = var
70  exit
71  endif
72 enddo
73 
74 end function has_field
75 
76 ! --------------------------------------------------------------------------------------------------
77 
78 subroutine get_field_return_type_pointer(fields, field_name, field)
79 
80 type(fv3jedi_field), target, intent(in) :: fields(:)
81 character(len=*), intent(in) :: field_name
82 type(fv3jedi_field), pointer, intent(out) :: field
83 
84 integer :: var
85 logical :: found
86 
87 if(associated(field)) nullify(field)
88 
89 found = .false.
90 do var = 1,size(fields)
91  if ( trim(fields(var)%fv3jedi_name) == trim(field_name)) then
92  field => fields(var)
93  found = .true.
94  exit
95  endif
96 enddo
97 
98 if (.not.found) call abor1_ftn("fv3jedi_field.get_field_return_type_pointer: field "&
99  //trim(field_name)//" not found in fields")
100 
101 end subroutine get_field_return_type_pointer
102 
103 ! --------------------------------------------------------------------------------------------------
104 
105 subroutine get_field_return_array_pointer(fields, field_name, field)
106 
107 type(fv3jedi_field), target, intent(in) :: fields(:)
108 character(len=*), intent(in) :: field_name
109 real(kind=kind_real), pointer, intent(out) :: field(:,:,:)
110 
111 integer :: var
112 logical :: found
113 
114 if(associated(field)) nullify(field)
115 
116 found = .false.
117 do var = 1,size(fields)
118  if ( trim(fields(var)%fv3jedi_name) == trim(field_name)) then
119  field => fields(var)%array
120  found = .true.
121  exit
122  endif
123 enddo
124 
125 if (.not.found) call abor1_ftn("fv3jedi_field.get_field_return_array_pointer: field "&
126  //trim(field_name)//" not found in fields")
127 
128 end subroutine get_field_return_array_pointer
129 
130 ! --------------------------------------------------------------------------------------------------
131 
132 subroutine get_field_return_array_allocatable(fields, field_name, field)
133 
134 type(fv3jedi_field), intent(in) :: fields(:)
135 character(len=*), intent(in) :: field_name
136 real(kind=kind_real), allocatable, intent(out) :: field(:,:,:)
137 
138 integer :: var
139 logical :: found, boundsmatch
140 
141 found = .false.
142 do var = 1, size(fields)
143  if ( trim(fields(var)%fv3jedi_name) == trim(field_name)) then
144 
145  if (.not. allocated(field)) then
146  ! If not allocated allocate
147  else
148  ! If allocated check bounds
149  boundsmatch = lbound(field,1) == fields(var)%isc .and. ubound(field,1) == fields(var)%iec .and. &
150  lbound(field,2) == fields(var)%jsc .and. ubound(field,2) == fields(var)%jec .and. &
151  lbound(field,3) == 1 .and. ubound(field,3) == fields(var)%npz
152  if (.not.boundsmatch) call abor1_ftn("get_field_return_array_allocatable: field "//&
153  trim(field_name)//" bounds mismatch")
154  endif
155 
156  ! Copy the field
157  field = fields(var)%array
158 
159  ! Set found flag
160  found = .true.
161 
162  exit
163  endif
164 enddo
165 
166 if (.not.found) call abor1_ftn("get_field_return_array_allocatable: field "//trim(field_name)//&
167  " not found in fields")
168 
170 
171 
172 ! --------------------------------------------------------------------------------------------------
173 
174 subroutine put_field(fields, field_name, field)
175 
176 type(fv3jedi_field), intent(inout) :: fields(:)
177 character(len=*), intent(in) :: field_name
178 real(kind=kind_real), allocatable, intent(in) :: field(:,:,:)
179 
180 integer :: var
181 logical :: found, boundsmatch
182 
183 if (.not. allocated(field)) call abor1_ftn("put_field: field "//trim(field_name)//" not allocated")
184 
185 found = .false.
186 do var = 1, size(fields)
187  if ( trim(fields(var)%fv3jedi_name) == trim(field_name)) then
188 
189  ! Check for matching bounds
190  boundsmatch = lbound(field,1) == fields(var)%isc .and. ubound(field,1) == fields(var)%iec .and. &
191  lbound(field,2) == fields(var)%jsc .and. ubound(field,2) == fields(var)%jec .and. &
192  lbound(field,3) == 1 .and. ubound(field,3) == fields(var)%npz
193  if (.not.boundsmatch) call abor1_ftn("put_field: field "//trim(field_name)//" bounds mismatch")
194 
195  ! Copy the field
196  fields(var)%array = field
197 
198  ! Set found flag
199  found = .true.
200 
201  exit
202  endif
203 enddo
204 
205 if (.not.found) call abor1_ftn("put_field: field "//trim(field_name)//" not found in fields")
206 
207 end subroutine put_field
208 
209 ! --------------------------------------------------------------------------------------------------
210 
211 subroutine checksame(fields1, fields2, calling_method)
212 
213 implicit none
214 type(fv3jedi_field), intent(in) :: fields1(:)
215 type(fv3jedi_field), intent(in) :: fields2(:)
216 character(len=*), intent(in) :: calling_method
217 
218 integer :: var
219 
220 if (size(fields1) .ne. size(fields2)) then
221  call abor1_ftn(trim(calling_method)//"(checksame): Different number of fields")
222 endif
223 
224 do var = 1,size(fields1)
225  if (fields1(var)%fv3jedi_name .ne. fields2(var)%fv3jedi_name) then
226  call abor1_ftn(trim(calling_method)//"(checksame): field "//trim(fields1(var)%fv3jedi_name)//&
227  " not in the equivalent position in the right hand side")
228  endif
229 enddo
230 
231 end subroutine checksame
232 
233 ! ------------------------------------------------------------------------------
234 
235 subroutine copy_subset(field_in, field_ou, not_copied)
236 
237 implicit none
238 type(fv3jedi_field), intent(in) :: field_in(:)
239 type(fv3jedi_field), intent(inout) :: field_ou(:)
240 character(len=field_clen), allocatable, optional, intent(out) :: not_copied(:)
241 
242 integer :: var
243 character(len=field_clen) :: not_copied_(10000)
244 integer :: num_not_copied
245 
246 ! Loop over fields and copy if existing in both
247 num_not_copied = 0
248 do var = 1, size(field_ou)
249  if (has_field(field_in, field_ou(var)%fv3jedi_name )) then
250  call get_field(field_in, field_ou(var)%fv3jedi_name, field_ou(var)%array)
251  else
252  num_not_copied = num_not_copied + 1
253  not_copied_(num_not_copied) = field_ou(var)%fv3jedi_name
254  endif
255 enddo
256 
257 ! Send back list of variables not retrivable from field_in
258 if (present(not_copied) .and. num_not_copied > 0) then
259  allocate(not_copied(num_not_copied))
260  not_copied(1:num_not_copied) = not_copied_(1:num_not_copied)
261 endif
262 
263 end subroutine copy_subset
264 
265 ! --------------------------------------------------------------------------------------------------
266 
267 subroutine long_name_to_fv3jedi_name(fields, long_name, fv3jedi_name)
268 
269 type(fv3jedi_field), intent(in) :: fields(:)
270 character(len=*), intent(in) :: long_name
271 character(len=*), intent(out) :: fv3jedi_name
272 
273 integer :: n
274 
275 do n = 1, size(fields)
276  if (trim(long_name) == trim(fields(n)%long_name)) then
277  fv3jedi_name = trim(fields(n)%fv3jedi_name)
278  return
279  endif
280 enddo
281 
282 ! Try with increment_of_ prepended to long_name
283 do n = 1, size(fields)
284  if ("increment_of_"//trim(long_name) == trim(fields(n)%long_name)) then
285  fv3jedi_name = trim(fields(n)%fv3jedi_name)
286  return
287  endif
288 enddo
289 
290 call abor1_ftn("fv3jedi_field_mod.long_name_to_fv3jedi_name long_name "//trim(long_name)//&
291  " not found in fields.")
292 
293 end subroutine long_name_to_fv3jedi_name
294 
295 ! --------------------------------------------------------------------------------------------------
296 
297 end module fv3jedi_field_mod
fv3jedi_field_mod::checksame
subroutine, public checksame(fields1, fields2, calling_method)
Definition: fv3jedi_field_mod.f90:212
fv3jedi_field_mod
Definition: fv3jedi_field_mod.f90:6
fv3jedi_field_mod::has_field
logical function, public has_field(fields, field_name, field_index)
Definition: fv3jedi_field_mod.f90:58
fv3jedi_field_mod::get_field_return_array_allocatable
subroutine get_field_return_array_allocatable(fields, field_name, field)
Definition: fv3jedi_field_mod.f90:133
fv3jedi_field_mod::copy_subset
subroutine, public copy_subset(field_in, field_ou, not_copied)
Definition: fv3jedi_field_mod.f90:236
fv3jedi_field_mod::put_field
subroutine, public put_field(fields, field_name, field)
Definition: fv3jedi_field_mod.f90:175
fv3jedi_field_mod::get_field
Definition: fv3jedi_field_mod.f90:25
fv3jedi_field_mod::get_field_return_array_pointer
subroutine get_field_return_array_pointer(fields, field_name, field)
Definition: fv3jedi_field_mod.f90:106
fv3jedi_field_mod::long_name_to_fv3jedi_name
subroutine, public long_name_to_fv3jedi_name(fields, long_name, fv3jedi_name)
Definition: fv3jedi_field_mod.f90:268
fv3jedi_kinds_mod::kind_real
integer, parameter, public kind_real
Definition: fv3jedi_kinds_mod.f90:14
fv3jedi_field_mod::fv3jedi_field
Definition: fv3jedi_field_mod.f90:36
fv3jedi_kinds_mod
Definition: fv3jedi_kinds_mod.f90:6
fv3jedi_field_mod::get_field_return_type_pointer
subroutine get_field_return_type_pointer(fields, field_name, field)
Definition: fv3jedi_field_mod.f90:79
fv3jedi_field_mod::field_clen
integer, parameter, public field_clen
Definition: fv3jedi_field_mod.f90:31