FV3-JEDI
fv3jedi_state_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 ! iso
9 use iso_c_binding
10 
11 ! oops uses
12 use datetime_mod
13 
14 ! fckit uses
15 use fckit_configuration_module, only: fckit_configuration
16 use fckit_log_module, only : log
17 
18 ! fv3jedi uses
23 use wind_vt_mod, only: a2d
24 
25 implicit none
26 private
27 public :: fv3jedi_state
28 
29 !> Fortran derived type to hold FV3JEDI state
30 type, extends(fv3jedi_fields) :: fv3jedi_state
31 contains
32  procedure, public :: add_incr
33  procedure, public :: analytic_ic
34 end type fv3jedi_state
35 
36 ! --------------------------------------------------------------------------------------------------
37 
38 contains
39 
40 ! --------------------------------------------------------------------------------------------------
41 
42 subroutine add_incr(self, geom, rhs_fields)
43 
44 implicit none
45 class(fv3jedi_state), intent(inout) :: self
46 type(fv3jedi_geom), intent(inout) :: geom
47 type(fv3jedi_field), intent(in) :: rhs_fields(:)
48 
49 integer :: var, i, j, k, isc, iec, jsc, jec, npz
50 logical :: found_neg
51 type(fv3jedi_field), pointer :: field_pointer
52 
53 real(kind=kind_real), allocatable :: rhs_ud(:,:,:), rhs_vd(:,:,:)
54 real(kind=kind_real), allocatable :: rhs_delp(:,:,:)
55 
56 real(kind=kind_real), pointer :: self_ua(:,:,:)
57 real(kind=kind_real), pointer :: self_va(:,:,:)
58 real(kind=kind_real), pointer :: self_ud(:,:,:)
59 real(kind=kind_real), pointer :: self_vd(:,:,:)
60 real(kind=kind_real), pointer :: self_t(:,:,:)
61 real(kind=kind_real), pointer :: self_pt(:,:,:)
62 real(kind=kind_real), pointer :: self_delp(:,:,:)
63 real(kind=kind_real), pointer :: self_ps(:,:,:)
64 
65 real(kind=kind_real), pointer :: rhs_ua(:,:,:)
66 real(kind=kind_real), pointer :: rhs_va(:,:,:)
67 real(kind=kind_real), pointer :: rhs_t(:,:,:)
68 real(kind=kind_real), pointer :: rhs_pt(:,:,:)
69 real(kind=kind_real), pointer :: rhs_ps(:,:,:)
70 
71 ! Convenience
72 ! -----------
73 isc = geom%isc
74 iec = geom%iec
75 jsc = geom%jsc
76 jec = geom%jec
77 npz = geom%npz
78 
79 ! Handle special cases, e.g. D grid winds to A grid winds
80 ! -------------------------------------------------------
81 
82 ! Get D-Grid winds if necessary
83 if (has_field(rhs_fields, 'ua')) then !A-Grid in increment
84  if (.not.has_field(rhs_fields, 'ud')) then !D-Grid not in increment
85  if (self%has_field('ud')) then !D-grid in state
86  allocate(rhs_ud(isc:iec ,jsc:jec+1,1:npz))
87  allocate(rhs_vd(isc:iec+1,jsc:jec ,1:npz))
88  call get_field(rhs_fields, 'ua', rhs_ua)
89  call get_field(rhs_fields, 'va', rhs_va)
90  call a2d(geom, rhs_ua, rhs_va, rhs_ud, rhs_vd) !Linear
91  endif
92  endif
93 endif
94 
95 
96 ! Convert ps to delp if necessary
97 ! -------------------------------
98 if (has_field(rhs_fields, 'ps')) then !ps in increment
99  if (.not.has_field(rhs_fields, 'delp')) then !delp not in increment
100  if (self%has_field('delp')) then !delp in state
101  allocate(rhs_delp(isc:iec,jsc:jec,1:npz))
102  call get_field(rhs_fields, 'ps', rhs_ps)
103  do k = 1, npz
104  rhs_delp(:,:,k) = (geom%bk(k+1)-geom%bk(k))*rhs_ps(:,:,1) !TLM
105  enddo
106  endif
107  endif
108 endif
109 
110 !Fields to add determined from increment
111 do var = 1, size(rhs_fields)
112 
113  !Winds are a special case
114  if (rhs_fields(var)%fv3jedi_name == 'ua') then
115 
116  if (self%has_field('ua')) then
117  call get_field(rhs_fields, 'ua', rhs_ua)
118  call self%get_field('ua', self_ua)
119  self_ua = self_ua + rhs_ua
120  endif
121  if (self%has_field('ud') .and. .not.has_field(rhs_fields, 'ud')) then
122  call self%get_field('ud', self_ud)
123  self_ud = self_ud + rhs_ud
124  endif
125 
126  elseif (rhs_fields(var)%fv3jedi_name == 'va') then
127 
128  if (self%has_field('va')) then
129  call get_field(rhs_fields, 'va', rhs_va)
130  call self%get_field('va', self_va)
131  self_va = self_va + rhs_va
132  endif
133  if (self%has_field('vd') .and. .not.has_field(rhs_fields, 'vd')) then
134  call self%get_field('vd', self_vd)
135  self_vd = self_vd + rhs_vd
136  endif
137 
138  elseif (rhs_fields(var)%fv3jedi_name == 't') then
139 
140  if (self%has_field('t')) then
141  call get_field(rhs_fields, 't', rhs_t)
142  call self%get_field('t', self_t)
143  self_t = self_t + rhs_t
144  endif
145 
146  if (self%has_field('pt')) then
147  call get_field(rhs_fields, 'pt', rhs_pt)
148  call self%get_field('pt', self_pt)
149  self_pt = self_pt + rhs_pt
150  endif
151 
152  elseif (rhs_fields(var)%fv3jedi_name == 'ps') then
153 
154  if (self%has_field('ps')) then
155  call get_field(rhs_fields, 'ps', rhs_ps)
156  call self%get_field('ps', self_ps)
157  self_ps = self_ps + rhs_ps
158  endif
159 
160  if (self%has_field('delp') .and. .not. has_field(rhs_fields, 'delp')) then
161  call self%get_field('delp', self_delp)
162  self_delp = self_delp + rhs_delp
163  endif
164 
165  else
166 
167  !Get pointer to state
168  call self%get_field(rhs_fields(var)%fv3jedi_name, field_pointer)
169 
170  !Add increment to state
171  field_pointer%array = field_pointer%array + rhs_fields(var)%array
172 
173  !Nullify pointer
174  nullify(field_pointer)
175 
176  endif
177 
178 enddo
179 
180 if (allocated(rhs_ud)) deallocate(rhs_ud)
181 if (allocated(rhs_vd)) deallocate(rhs_vd)
182 if (allocated(rhs_delp)) deallocate(rhs_delp)
183 
184 !Check for negative tracers and increase to 0.0
185 do var = 1,self%nf
186 
187  if (self%fields(var)%tracer) then
188 
189  found_neg = .false.
190 
191  do k = 1, self%fields(var)%npz
192  do j = jsc, jec
193  do i = isc, iec
194  if (self%fields(var)%array(i,j,k) < 0.0_kind_real) then
195  found_neg = .true.
196  self%fields(var)%array(i,j,k) = 0.0_kind_real
197  endif
198  enddo
199  enddo
200  enddo
201 
202  !Print message warning about negative tracer removal
203  if (found_neg .and. self%f_comm%rank() == 0) print*, &
204  'fv3jedi_state_mod.add_incr: Removed negative values for '&
205  //trim(self%fields(var)%fv3jedi_name)
206 
207  endif
208 
209 enddo
210 
211 end subroutine add_incr
212 
213 ! --------------------------------------------------------------------------------------------------
214 !> Analytic Initialization for the FV3 Model
215 !!
216 !! \details **analytic_IC()** initializes the FV3JEDI state and State objects using one of
217 !! several alternative idealized analytic models. This is intended to facilitate testing by
218 !! eliminating the need to read in the initial state from a file and by providing exact expressions
219 !! to test interpolations. This function is activated by setting the "analytic_init" state in the
220 !! "initial" or "statefile" section of the configuration file.
221 !!
222 !! Initialization options that begin with "dcmip" refer to tests defined by the multi-institutional
223 !! 2012 [Dynamical Core Intercomparison Project](https://earthsystealcmcog.org/projects/dcmip-2012)
224 !! and the associated Summer School, sponsored by NOAA, NSF, DOE, NCAR, and the University of
225 !! Michigan.
226 !!
227 !! Currently implemented options for analytic_init include:
228 !! * dcmip-test-1-1: 3D deformational flow
229 !! * dcmip-test-1-2: 3D Hadley-like meridional circulation
230 !! * dcmip-test-3-1: Non-hydrostatic gravity wave
231 !! * dcmip-test-4-0: Baroclinic instability
232 !!
233 !! \author M. Miesch (adapted from a pre-existing call to invent_state)
234 !! \date March, 2018: Created
235 !! \date May, 2018: Added dcmip-test-3-1
236 !! \date June, 2018: Added dcmip-test-4-0
237 !!
238 !! \warning This routine does not initialize the fv3jedi_interp member of the fv3jedi_state object
239 !!
240 !! \warning Though an input state file is not required for these analytic initialization routines,
241 !! some grid information (in particular the hybrid vertical grid coefficients ak and bk)
242 !! is still read in from an input file when creating the geometry object that is a required
243 !! member of fv3jedi_state; see c_fv3jedi_geo_setup() in fv3jedi_geom_mod.F90.
244 !!
245 !!
246 subroutine analytic_ic(self, geom, conf, vdate)
247 
248  use dcmip_initial_conditions_test_1_2_3, only : test1_advection_deformation, &
249  test1_advection_hadley, test3_gravity_wave
250  use dcmip_initial_conditions_test_4, only : test4_baroclinic_wave
251 
252  implicit none
253 
254  class(fv3jedi_state), intent(inout) :: self !< State
255  type(fv3jedi_geom), intent(inout) :: geom !< Geometry
256  type(fckit_configuration), intent(in) :: conf !< Configuration
257  type(datetime), intent(inout) :: vdate !< DateTime
258 
259  character(len=30) :: IC
260  character(len=20) :: sdate
261  character(len=1024) :: buf
262  Integer :: i,j,k
263  real(kind=kind_real) :: rlat, rlon
264  real(kind=kind_real) :: pk,pe1,pe2,ps
265  real(kind=kind_real) :: u0,v0,w0,t0,phis0,ps0,rho0,hum0,q1,q2,q3,q4
266 
267  character(len=:), allocatable :: str
268 
269  real(kind=kind_real), pointer :: ud(:,:,:)
270  real(kind=kind_real), pointer :: vd(:,:,:)
271  real(kind=kind_real), pointer :: t(:,:,:)
272  real(kind=kind_real), pointer :: delp(:,:,:)
273  real(kind=kind_real), pointer :: q(:,:,:)
274  real(kind=kind_real), pointer :: qi(:,:,:)
275  real(kind=kind_real), pointer :: ql(:,:,:)
276  real(kind=kind_real), pointer :: o3(:,:,:)
277  real(kind=kind_real), pointer :: phis(:,:,:)
278  real(kind=kind_real), pointer :: w(:,:,:)
279  real(kind=kind_real), pointer :: delz(:,:,:)
280 
281 
282  If (conf%has("analytic_init")) Then
283  call conf%get_or_die("analytic_init",str)
284  ic = str
285  deallocate(str)
286  EndIf
287 
288  call log%warning("fv3jedi_state:analytic_init: "//ic)
289  call conf%get_or_die("date",str)
290  sdate = str
291  deallocate(str)
292  WRITE(buf,*) 'validity date is: '//sdate
293  call log%info(buf)
294  call datetime_set(sdate, vdate)
295 
296  !Pointers to states
297  call self%get_field('ud' , ud )
298  call self%get_field('vd' , vd )
299  call self%get_field('t' , t )
300  call self%get_field('delp' , delp)
301  call self%get_field('sphum' , q )
302  call self%get_field('ice_wat', qi )
303  call self%get_field('liq_wat', ql )
304  call self%get_field('phis' , phis)
305  if ( self%has_field('o3mr' )) call self%get_field('o3mr' , o3)
306  if ( self%has_field('o3ppmv')) call self%get_field('o3ppmv', o3)
307  if (self%has_field('w' )) call self%get_field('w' , w )
308  if (self%has_field('delz')) call self%get_field('delz', delz)
309 
310  int_option: Select Case (ic)
311 
312  Case ("dcmip-test-1-1")
313 
314  do i = geom%isc,geom%iec
315  do j = geom%jsc,geom%jec
316  rlat = geom%grid_lat(i,j)
317  rlon = geom%grid_lon(i,j)
318 
319  ! Call the routine first just to get the surface pressure
320  Call test1_advection_deformation(rlon,rlat,pk,0.d0,1,u0,v0,w0,t0,&
321  phis0,ps,rho0,hum0,q1,q2,q3,q4)
322 
323  phis(i,j,1) = phis0
324 
325  ! Now loop over all levels
326  do k = 1, geom%npz
327 
328  pe1 = geom%ak(k) + geom%bk(k)*ps
329  pe2 = geom%ak(k+1) + geom%bk(k+1)*ps
330  pk = 0.5_kind_real * (pe1+pe2)
331  Call test1_advection_deformation(rlon,rlat,pk,0.d0,0,u0,v0,w0,t0,&
332  phis0,ps0,rho0,hum0,q1,q2,q3,q4)
333 
334  ud(i,j,k) = u0
335  vd(i,j,k) = v0
336  If (self%has_field('w')) w(i,j,k) = w0
337  t(i,j,k) = t0
338  delp(i,j,k) = pe2-pe1
339  q(i,j,k) = hum0
340  qi(i,j,k) = q1
341  ql(i,j,k) = q2
342  o3(i,j,k) = q3
343 
344  enddo
345  enddo
346  enddo
347 
348  Case ("dcmip-test-1-2")
349 
350  do i = geom%isc,geom%iec
351  do j = geom%jsc,geom%jec
352  rlat = geom%grid_lat(i,j)
353  rlon = geom%grid_lon(i,j)
354 
355  ! Call the routine first just to get the surface pressure
356  Call test1_advection_hadley(rlon,rlat,pk,0.d0,1,u0,v0,w0,&
357  t0,phis0,ps,rho0,hum0,q1)
358 
359  phis(i,j,1) = phis0
360 
361  ! Now loop over all levels
362  do k = 1, geom%npz
363 
364  pe1 = geom%ak(k) + geom%bk(k)*ps
365  pe2 = geom%ak(k+1) + geom%bk(k+1)*ps
366  pk = 0.5_kind_real * (pe1+pe2)
367  Call test1_advection_hadley(rlon,rlat,pk,0.d0,0,u0,v0,w0,&
368  t0,phis0,ps,rho0,hum0,q1)
369 
370  ud(i,j,k) = u0 !ATTN comment above
371  vd(i,j,k) = v0
372  If (self%has_field('w')) w(i,j,k) = w0
373  t(i,j,k) = t0
374  delp(i,j,k) = pe2-pe1
375  q(i,j,k) = hum0
376  qi(i,j,k) = q1
377 
378  enddo
379  enddo
380  enddo
381 
382  Case ("dcmip-test-3-1")
383 
384  do i = geom%isc,geom%iec
385  do j = geom%jsc,geom%jec
386  rlat = geom%grid_lat(i,j)
387  rlon = geom%grid_lon(i,j)
388 
389  ! Call the routine first just to get the surface pressure
390  Call test3_gravity_wave(rlon,rlat,pk,0.d0,1,u0,v0,w0,&
391  t0,phis0,ps,rho0,hum0)
392 
393  phis(i,j,1) = phis0
394 
395  ! Now loop over all levels
396  do k = 1, geom%npz
397 
398  pe1 = geom%ak(k) + geom%bk(k)*ps
399  pe2 = geom%ak(k+1) + geom%bk(k+1)*ps
400  pk = 0.5_kind_real * (pe1+pe2)
401  Call test3_gravity_wave(rlon,rlat,pk,0.d0,0,u0,v0,w0,&
402  t0,phis0,ps,rho0,hum0)
403 
404  ud(i,j,k) = u0 !ATTN comment above
405  vd(i,j,k) = v0
406  If (self%has_field('w')) w(i,j,k) = w0
407  t(i,j,k) = t0
408  delp(i,j,k) = pe2-pe1
409  q(i,j,k) = hum0
410 
411  enddo
412  enddo
413  enddo
414 
415  Case ("dcmip-test-4-0")
416 
417  do i = geom%isc,geom%iec
418  do j = geom%jsc,geom%jec
419  rlat = geom%grid_lat(i,j)
420  rlon = geom%grid_lon(i,j)
421 
422  ! Call the routine first just to get the surface pressure
423  Call test4_baroclinic_wave(0,1.0_kind_real,rlon,rlat,pk,0.d0,1,u0,v0,w0,&
424  t0,phis0,ps,rho0,hum0,q1,q2)
425 
426  phis(i,j,1) = phis0
427 
428  ! Now loop over all levels
429  do k = 1, geom%npz
430 
431  pe1 = geom%ak(k) + geom%bk(k)*ps
432  pe2 = geom%ak(k+1) + geom%bk(k+1)*ps
433  pk = 0.5_kind_real * (pe1+pe2)
434  Call test4_baroclinic_wave(0,1.0_kind_real,rlon,rlat,pk,0.d0,0,u0,v0,w0,&
435  t0,phis0,ps,rho0,hum0,q1,q2)
436 
437  ud(i,j,k) = u0 !ATTN comment above
438  vd(i,j,k) = v0
439  If (self%has_field('w')) w(i,j,k) = w0
440  t(i,j,k) = t0
441  delp(i,j,k) = pe2-pe1
442  q(i,j,k) = hum0
443 
444  enddo
445  enddo
446  enddo
447 
448  Case Default
449 
450  call abor1_ftn("fv3jedi_state analytic_IC: provide analytic_init")
451 
452  End Select int_option
453 
454 end subroutine analytic_ic
455 
456 ! --------------------------------------------------------------------------------------------------
457 
458 end module fv3jedi_state_mod
fv3jedi_field_mod::checksame
subroutine, public checksame(fields1, fields2, calling_method)
Definition: fv3jedi_field_mod.f90:212
fv3jedi_state_mod::fv3jedi_state
Fortran derived type to hold FV3JEDI state.
Definition: fv3jedi_state_mod.F90:30
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_state_mod::add_incr
subroutine add_incr(self, geom, rhs_fields)
Definition: fv3jedi_state_mod.F90:43
fv3jedi_state_mod::analytic_ic
subroutine analytic_ic(self, geom, conf, vdate)
Analytic Initialization for the FV3 Model.
Definition: fv3jedi_state_mod.F90:247
fv3jedi_state_mod
Definition: fv3jedi_state_mod.F90:6
fv3jedi_geom_mod
Fortran module handling geometry for the FV3 model.
Definition: fv3jedi_geom_mod.f90:8
fv3jedi_field_mod::get_field
Definition: fv3jedi_field_mod.f90:25
fv3jedi_geom_mod::fv3jedi_geom
Fortran derived type to hold geometry data for the FV3JEDI model.
Definition: fv3jedi_geom_mod.f90:46
wind_vt_mod
Definition: wind_variables_mod.f90:6
fv3jedi_kinds_mod::kind_real
integer, parameter, public kind_real
Definition: fv3jedi_kinds_mod.f90:14
wind_vt_mod::a2d
subroutine, public a2d(geom, ua, va, ud, vd)
Definition: wind_variables_mod.f90:1023
fv3jedi_field_mod::fv3jedi_field
Definition: fv3jedi_field_mod.f90:36
fv3jedi_fields_mod
Definition: fv3jedi_fields_mod.f90:6
fv3jedi_kinds_mod
Definition: fv3jedi_kinds_mod.f90:6
fv3jedi_fields_mod::fv3jedi_fields
Definition: fv3jedi_fields_mod.f90:34