OOPS
qg_fields_mod.F90
Go to the documentation of this file.
1 ! (C) Copyright 2009-2016 ECMWF.
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 ! In applying this licence, ECMWF does not waive the privileges and immunities
6 ! granted to it by virtue of its status as an intergovernmental organisation nor
7 ! does it submit to any jurisdiction.
8 
10 
11 use atlas_module, only: atlas_field, atlas_fieldset, atlas_real
12 use fckit_configuration_module, only: fckit_configuration
13 use datetime_mod
14 use duration_mod
15 use fckit_log_module,only: fckit_log
16 use iso_c_binding
17 use kinds
18 use missing_values_mod
19 use netcdf
20 !$ use omp_lib
26 use qg_geom_mod
28 use qg_gom_mod
29 use qg_interp_mod
30 use qg_locs_mod
31 use qg_tools_mod
33 use random_mod
34 
35 implicit none
36 
37 private
38 public :: qg_fields
39 public :: qg_fields_registry
48 ! ------------------------------------------------------------------------------
49 integer,parameter :: rseed = 7 !< Random seed (for reproducibility)
50 
51 type :: qg_fields
52  type(qg_geom),pointer :: geom !< Geometry
53  logical :: lq !< PV as main variable (streamfunction if false)
54  logical :: lbc !< Boundaries are present
55  real(kind_real),allocatable :: gfld3d(:,:,:) !< 3d field
56  real(kind_real),allocatable :: x_north(:) !< Streamfunction on northern wall
57  real(kind_real),allocatable :: x_south(:) !< Streamfunction on southern wall
58  real(kind_real),allocatable :: q_north(:,:) !< PV on northern wall
59  real(kind_real),allocatable :: q_south(:,:) !< PV on southern wall
60 end type qg_fields
61 
62 #define LISTED_TYPE qg_fields
63 
64 !> Linked list interface - defines registry_t type
65 #include "oops/util/linkedList_i.f"
66 
67 !> Global registry
68 type(registry_t) :: qg_fields_registry
69 ! ------------------------------------------------------------------------------
70 contains
71 ! ------------------------------------------------------------------------------
72 ! Public
73 ! ------------------------------------------------------------------------------
74 !> Linked list implementation
75 #include "oops/util/linkedList_c.f"
76 ! ------------------------------------------------------------------------------
77 !> Create fields from geometry and variables
78 subroutine qg_fields_create(self,geom,vars,lbc)
79 
80 implicit none
81 
82 ! Passed variables
83 type(qg_fields),intent(inout) :: self !< Fields
84 type(qg_geom),target,intent(in) :: geom !< Geometry
85 type(oops_variables),intent(in) :: vars !< Variables
86 logical,intent(in) :: lbc !< Boundaries flag
87 
88 ! Local variables
89 character(len=1024) :: record
90 
91 ! Associate geometry
92 self%geom => geom
93 
94 ! Set variables
95 if (vars%has('x') .and. vars%has('q')) then
96  call abor1_ftn('qg_fields_create: x and q cannot be set as fields together')
97 elseif (vars%has('u') .or. vars%has('v')) then
98  call abor1_ftn('qg_fieldsçcreate: u and v cannot be set as fields')
99 elseif (vars%has('x')) then
100  self%lq = .false.
101 elseif (vars%has('q')) then
102  self%lq = .true.
103 else
104  call abor1_ftn('qg_fields_create: x or q should be set as fields')
105 endif
106 
107 ! Set boundaries
108 self%lbc = lbc
109 
110 ! Allocate 3d field
111 allocate(self%gfld3d(self%geom%nx,self%geom%ny,self%geom%nz))
112 
113 ! Allocate boundaries
114 if (self%lbc) then
115  ! Allocation
116  allocate(self%x_north(self%geom%nz))
117  allocate(self%x_south(self%geom%nz))
118  allocate(self%q_north(self%geom%nx,self%geom%nz))
119  allocate(self%q_south(self%geom%nx,self%geom%nz))
120 endif
121 
122 ! Initialize
123 call qg_fields_zero(self)
124 
125 end subroutine qg_fields_create
126 
127 !> Create fields from geometry (x)
128 subroutine qg_fields_create_default(self,geom,lbc)
129 
130 implicit none
131 
132 ! Passed variables
133 type(qg_fields),intent(inout) :: self !< Fields
134 type(qg_geom),target,intent(in) :: geom !< Geometry
135 logical,intent(in) :: lbc !< Boundaries flag
136 
137 ! Local variables
138 character(len=1024) :: record
139 
140 ! Associate geometry
141 self%geom => geom
142 
143 ! Set variables
144 self%lq = .false.
145 
146 ! Set boundaries
147 self%lbc = lbc
148 
149 ! Allocate 3d field
150 allocate(self%gfld3d(self%geom%nx,self%geom%ny,self%geom%nz))
151 
152 ! Allocate boundaries
153 if (self%lbc) then
154  ! Allocation
155  allocate(self%x_north(self%geom%nz))
156  allocate(self%x_south(self%geom%nz))
157  allocate(self%q_north(self%geom%nx,self%geom%nz))
158  allocate(self%q_south(self%geom%nx,self%geom%nz))
159 endif
160 
161 ! Initialize
162 call qg_fields_zero(self)
163 
164 end subroutine qg_fields_create_default
165 ! ------------------------------------------------------------------------------
166 !> Create fields from another one
167 subroutine qg_fields_create_from_other(self,other)
168 
169 implicit none
170 
171 ! Passed variables
172 type(qg_fields),intent(inout) :: self !< Fields
173 type(qg_fields),intent(in) :: other !< Other fields
174 
175 ! Associate geometry
176 self%geom => other%geom
177 
178 ! Copy attributes
179 self%lq = other%lq
180 self%lbc = other%lbc
181 
182 ! Allocate 3d field
183 allocate(self%gfld3d(self%geom%nx,self%geom%ny,self%geom%nz))
184 
185 ! Allocate boundaries
186 if (self%lbc) then
187  ! Allocation
188  allocate(self%x_north(self%geom%nz))
189  allocate(self%x_south(self%geom%nz))
190  allocate(self%q_north(self%geom%nx,self%geom%nz))
191  allocate(self%q_south(self%geom%nx,self%geom%nz))
192 endif
193 
194 ! Initialize
195 call qg_fields_zero(self)
196 
197 end subroutine qg_fields_create_from_other
198 ! ------------------------------------------------------------------------------
199 !> Delete fields
200 subroutine qg_fields_delete(self)
201 
202 implicit none
203 
204 ! Passed variables
205 type(qg_fields),intent(inout) :: self !< Fields
206 
207 ! Release memory
208 if (allocated(self%gfld3d)) deallocate(self%gfld3d)
209 if (allocated(self%x_north)) deallocate(self%x_north)
210 if (allocated(self%x_south)) deallocate(self%x_south)
211 if (allocated(self%q_north)) deallocate(self%q_north)
212 if (allocated(self%q_south)) deallocate(self%q_south)
213 
214 end subroutine qg_fields_delete
215 ! ------------------------------------------------------------------------------
216 !> Set fields to zero
217 subroutine qg_fields_zero(self)
218 
219 implicit none
220 
221 ! Passed variables
222 type(qg_fields),intent(inout) :: self
223 
224 ! Check field
225 call qg_fields_check(self)
226 
227 ! Set fields to zero
228 self%gfld3d = 0.0
229 if (self%lbc) then
230  self%x_north = 0.0
231  self%x_south = 0.0
232  self%q_north = 0.0
233  self%q_south = 0.0
234 endif
235 
236 end subroutine qg_fields_zero
237 ! ------------------------------------------------------------------------------
238 !> Set fields to ones
239 subroutine qg_fields_ones(self)
240 
241 implicit none
242 
243 ! Passed variables
244 type(qg_fields),intent(inout) :: self
245 
246 ! Check field
247 call qg_fields_check(self)
248 
249 ! Set fields to ones
250 self%gfld3d = 1.0
251 if (self%lbc) then
252  self%x_north = 1.0
253  self%x_south = 1.0
254  self%q_north = 1.0
255  self%q_south = 1.0
256 endif
257 
258 end subroutine qg_fields_ones
259 ! ------------------------------------------------------------------------------
260 !> Set fields to Diracs
261 subroutine qg_fields_dirac(self,f_conf)
262 
263 implicit none
264 
265 ! Passed variables
266 type(qg_fields),intent(inout) :: self !< Fields
267 type(fckit_configuration),intent(in) :: f_conf !< FCKIT configuration
268 
269 ! Local variables
270 integer :: ndir,idir
271 integer,allocatable :: ixdir(:),iydir(:),izdir(:)
272 
273 ! Check field
274 call qg_fields_check(self)
275 
276 ! Get Diracs size
277 ndir = f_conf%get_size('ixdir')
278 if ((f_conf%get_size('iydir')/=ndir).or.(f_conf%get_size('izdir')/=ndir)) &
279  & call abor1_ftn('qg_fields_dirac: inconsistent sizes for ixdir, iydir and izdir')
280 
281 ! Allocation
282 allocate(ixdir(ndir))
283 allocate(iydir(ndir))
284 allocate(izdir(ndir))
285 
286 ! Get Diracs positions
287 call f_conf%get_or_die("ixdir",ixdir)
288 call f_conf%get_or_die("iydir",iydir)
289 call f_conf%get_or_die("izdir",izdir)
290 
291 ! Check Diracs positions
292 if (any(ixdir<1).or.any(ixdir>self%geom%nx)) call abor1_ftn('qg_fields_dirac: invalid ixdir')
293 if (any(iydir<1).or.any(iydir>self%geom%ny)) call abor1_ftn('qg_fields_dirac: invalid iydir')
294 if (any(izdir<1).or.any(izdir>self%geom%nz)) call abor1_ftn('qg_fields_dirac: invalid izdir')
295 
296 ! Setup Diracs
297 do idir=1,ndir
298  self%gfld3d(ixdir(idir),iydir(idir),izdir(idir)) = 1.0
299 end do
300 
301 end subroutine qg_fields_dirac
302 ! ------------------------------------------------------------------------------
303 !> Generate random fields
304 subroutine qg_fields_random(self)
305 
306 implicit none
307 
308 ! Passed variables
309 type(qg_fields),intent(inout) :: self !< Fields
310 
311 ! Check field
312 call qg_fields_check(self)
313 
314 ! Set at random value
315 call normal_distribution(self%gfld3d,0.0_kind_real,1.0_kind_real,rseed)
316 
317 end subroutine qg_fields_random
318 ! ------------------------------------------------------------------------------
319 !> Copy fields
320 subroutine qg_fields_copy(self,other,bconly)
321 
322 implicit none
323 
324 ! Passed variables
325 type(qg_fields),intent(inout) :: self !< Fields
326 type(qg_fields),intent(in) :: other !< Other fields
327 logical,intent(in),optional :: bconly !< Boundary condition only flag
328 
329 ! Local variables
330 logical :: lbconly
331 
332 ! Local flag
333 lbconly = .false.
334 if (present(bconly)) lbconly = bconly
335 
336 ! Check resolution
337 call qg_fields_check_resolution(self,other)
338 
339 if (.not.lbconly) then
340  ! Check variables
341  call qg_fields_check_variables(self,other)
342 
343  ! Copy 3D field
344  self%gfld3d = other%gfld3d
345 end if
346 
347 if (self%lbc) then
348  if (other%lbc) then
349  self%x_north = other%x_north
350  self%x_south = other%x_south
351  self%q_north = other%q_north
352  self%q_south = other%q_south
353  else
354  self%x_north = 0.0
355  self%x_south = 0.0
356  self%q_north = 0.0
357  self%q_south = 0.0
358  endif
359 endif
360 
361 end subroutine qg_fields_copy
362 ! ------------------------------------------------------------------------------
363 !> Add fields
364 subroutine qg_fields_self_add(self,rhs)
365 
366 implicit none
367 
368 ! Passed variables
369 type(qg_fields),intent(inout) :: self !< Fields
370 type(qg_fields),intent(in) :: rhs !< Right-hand side
371 
372 ! Check resolution
373 call qg_fields_check_resolution(self,rhs)
374 call qg_fields_check_variables(self,rhs)
375 
376 ! Add field
377 self%gfld3d = self%gfld3d+rhs%gfld3d
378 if (self%lbc.and.rhs%lbc) then
379  self%x_north = self%x_north+rhs%x_north
380  self%x_south = self%x_south+rhs%x_south
381  self%q_north = self%q_north+rhs%q_north
382  self%q_south = self%q_south+rhs%q_south
383 endif
384 
385 end subroutine qg_fields_self_add
386 ! ------------------------------------------------------------------------------
387 !> Subtract fields
388 subroutine qg_fields_self_sub(self,rhs)
389 
390 implicit none
391 
392 ! Passed variables
393 type(qg_fields),intent(inout) :: self !< Fields
394 type(qg_fields),intent(in) :: rhs !< Right-hand side
395 
396 ! Check resolution
397 call qg_fields_check_resolution(self,rhs)
398 call qg_fields_check_variables(self,rhs)
399 
400 ! Subtract field
401 self%gfld3d = self%gfld3d-rhs%gfld3d
402 if (self%lbc.and.rhs%lbc) then
403  self%x_north = self%x_north-rhs%x_north
404  self%x_south = self%x_south-rhs%x_south
405  self%q_north = self%q_north-rhs%q_north
406  self%q_south = self%q_south-rhs%q_south
407 endif
408 
409 end subroutine qg_fields_self_sub
410 ! ------------------------------------------------------------------------------
411 !> Multiply fields by a scalar
412 subroutine qg_fields_self_mul(self,zz)
413 
414 implicit none
415 
416 ! Passed variables
417 type(qg_fields),intent(inout) :: self !< Fields
418 real(kind_real),intent(in) :: zz !< Multiplier
419 
420 ! Check field
421 call qg_fields_check(self)
422 
423 ! Multiply with a scalar
424 self%gfld3d = zz*self%gfld3d
425 if (self%lbc) then
426  self%x_north = zz*self%x_north
427  self%x_south = zz*self%x_south
428  self%q_north = zz*self%q_north
429  self%q_south = zz*self%q_south
430 endif
431 
432 end subroutine qg_fields_self_mul
433 ! ------------------------------------------------------------------------------
434 !> Apply axpy operator to fields
435 subroutine qg_fields_axpy(self,zz,rhs)
436 
437 implicit none
438 
439 ! Passed variables
440 type(qg_fields),intent(inout) :: self !< Fields
441 real(kind_real),intent(in) :: zz !< Multiplier
442 type(qg_fields),intent(in) :: rhs !< Right-hand side
443 
444 ! Check resolution
445 call qg_fields_check_resolution(self,rhs)
446 call qg_fields_check_variables(self,rhs)
447 
448 ! Apply apxy
449 self%gfld3d = self%gfld3d+zz*rhs%gfld3d
450 if (self%lbc.and.rhs%lbc) then
451  self%x_north = self%x_north+zz*rhs%x_north
452  self%x_south = self%x_south+zz*rhs%x_south
453  self%q_north = self%q_north+zz*rhs%q_north
454  self%q_south = self%q_south+zz*rhs%q_south
455 endif
456 
457 end subroutine qg_fields_axpy
458 ! ------------------------------------------------------------------------------
459 !> Schur product of fields
460 subroutine qg_fields_self_schur(self,rhs)
461 
462 implicit none
463 
464 ! Passed variables
465 type(qg_fields),intent(inout) :: self !< Fields
466 type(qg_fields),intent(in) :: rhs !< Right-hand side
467 
468 ! Check resolution
469 call qg_fields_check_resolution(self,rhs)
470 call qg_fields_check_variables(self,rhs)
471 
472 ! Schur product
473 self%gfld3d = self%gfld3d*rhs%gfld3d
474 if (self%lbc.and.rhs%lbc) then
475  self%x_north = self%x_north*rhs%x_north
476  self%x_south = self%x_south*rhs%x_south
477  self%q_north = self%q_north*rhs%q_north
478  self%q_south = self%q_south*rhs%q_south
479 endif
480 
481 end subroutine qg_fields_self_schur
482 ! ------------------------------------------------------------------------------
483 !> Compute dot product for fields
484 subroutine qg_fields_dot_prod(fld1,fld2,zprod)
485 
486 implicit none
487 
488 ! Passed variables
489 type(qg_fields),intent(in) :: fld1 !< First fields
490 type(qg_fields),intent(in) :: fld2 !< Second fields
491 real(kind_real),intent(out) :: zprod !< Dot product
492 
493 ! Check resolution
494 call qg_fields_check_resolution(fld1,fld2)
495 call qg_fields_check_variables(fld1,fld2)
496 
497 ! Compute dot product
498 zprod = sum(fld1%gfld3d*fld2%gfld3d)
499 
500 end subroutine qg_fields_dot_prod
501 ! ------------------------------------------------------------------------------
502 !> Add increment to fields
503 subroutine qg_fields_add_incr(self,rhs)
504 
505 implicit none
506 
507 ! Passed variables
508 type(qg_fields),intent(inout) :: self !< Fields
509 type(qg_fields),intent(in) :: rhs !< Right-hand side
510 
511 ! Check fields
512 call qg_fields_check(self)
513 call qg_fields_check(rhs)
514 
515 if (self%lq.eqv.rhs%lq) then
516  if ((self%geom%nx==rhs%geom%nx).and.(self%geom%ny==rhs%geom%ny).and.(self%geom%nz==rhs%geom%nz)) then
517  ! Same resolution
518  self%gfld3d = self%gfld3d+rhs%gfld3d
519  else
520  ! Different resolutions
521  call abor1_ftn('qg_fields_add_incr: not coded for low res increment yet')
522  endif
523 else
524  call abor1_ftn('qg_fields_add_incr: different variables')
525 endif
526 
527 end subroutine qg_fields_add_incr
528 ! ------------------------------------------------------------------------------
529 !> Compute increment from the difference of two fields
530 subroutine qg_fields_diff_incr(lhs,fld1,fld2)
531 
532 implicit none
533 
534 ! Passed variables
535 type(qg_fields),intent(inout) :: lhs !< Left-hand side
536 type(qg_fields),intent(in) :: fld1 !< First fields
537 type(qg_fields),intent(in) :: fld2 !< Second fields
538 
539 ! Check resolution
540 call qg_fields_check_resolution(fld1,fld2)
541 call qg_fields_check_variables(fld1,fld2)
542 call qg_fields_check(lhs)
543 
544 ! Initialization
545 call qg_fields_zero(lhs)
546 
547 if (lhs%lq.eqv.fld1%lq) then
548  if ((fld1%geom%nx==lhs%geom%nx).and.(fld1%geom%ny==lhs%geom%ny).and.(fld1%geom%nz==lhs%geom%nz)) then
549  ! Same resolution
550  lhs%gfld3d = fld1%gfld3d-fld2%gfld3d
551  else
552  ! Different resolutions
553  call abor1_ftn('qg_fields_diff_incr: not coded for low res increment yet')
554  endif
555 else
556  call abor1_ftn('qg_fields_diff_incr: different variables')
557 endif
558 
559 end subroutine qg_fields_diff_incr
560 ! ------------------------------------------------------------------------------
561 !> Change fields resolution
562 subroutine qg_fields_change_resol(fld,rhs)
563 
564 implicit none
565 
566 ! Passed variables
567 type(qg_fields),intent(inout) :: fld !< Fields
568 type(qg_fields),intent(in) :: rhs !< Right-hand side
569 
570 integer :: ix,iy,iz
571 real(kind_real), allocatable, dimension(:,:,:) :: q1, q2
572 
573 ! Check fields
574 call qg_fields_check(fld)
575 call qg_fields_check(rhs)
576 
577 if (fld%lq.eqv.rhs%lq) then
578  if ((fld%geom%nx==rhs%geom%nx).and.(fld%geom%ny==rhs%geom%ny).and.(fld%geom%nz==rhs%geom%nz)) then
579  ! Same resolution
580  call qg_fields_copy(fld,rhs)
581  else
582  do ix = 1,fld%geom%nx
583  do iy = 1,fld%geom%ny
584  do iz = 1,fld%geom%nz
585  call qg_interp_trilinear( rhs%geom,fld%geom%lon(ix,iy),fld%geom%lat(ix,iy),fld%geom%z(iz), &
586  rhs%gfld3d,fld%gfld3d(ix,iy,iz) )
587  enddo
588  enddo
589  enddo
590  if (fld%lbc) then
591  if (rhs%lbc) then
592  allocate(q1(rhs%geom%nx,rhs%geom%ny,rhs%geom%nz))
593  allocate(q2(fld%geom%nx,fld%geom%ny,fld%geom%nz))
594  do iy = 1,rhs%geom%ny
595  q1(:,iy,:) = rhs%q_south
596  enddo
597  do ix = 1,fld%geom%nx
598  do iz = 1,fld%geom%nz
599  call qg_interp_trilinear( rhs%geom,fld%geom%lon(ix,1),fld%geom%lat(ix,1),fld%geom%z(iz), &
600  q1,q2(ix,1,iz) )
601  enddo
602  enddo
603  fld%q_south = q2(:,1,:)
604  do iy = 1,rhs%geom%ny
605  q1(:,iy,:) = rhs%q_north
606  enddo
607  do ix = 1,fld%geom%nx
608  do iz = 1,fld%geom%nz
609  call qg_interp_trilinear( rhs%geom,fld%geom%lon(ix,1),fld%geom%lat(ix,1),fld%geom%z(iz), &
610  q1,q2(ix,1,iz) )
611  enddo
612  enddo
613  fld%q_north = q2(:,1,:)
614  deallocate(q1,q2)
615  fld%x_north = rhs%x_north
616  fld%x_south = rhs%x_south
617  else
618  fld%x_north = 0.0
619  fld%x_south = 0.0
620  fld%q_north = 0.0
621  fld%q_south = 0.0
622  endif
623  endif
624  endif
625 else
626  call abor1_ftn('qg_fields_change_resol: different variables')
627 endif
628 
629 end subroutine qg_fields_change_resol
630 ! ------------------------------------------------------------------------------
631 !> Read fields from file
632 subroutine qg_fields_read_file(fld,f_conf,vdate)
633 use string_utils
634 
635 implicit none
636 
637 ! Passed variables
638 type(qg_fields),intent(inout) :: fld !< Fields
639 type(fckit_configuration),intent(in) :: f_conf !< FCKIT configuration
640 type(datetime),intent(inout) :: vdate !< Date and time
641 
642 ! Local variables
643 integer :: iread,nx,ny,nz,bc
644 integer :: ncid,nx_id,ny_id,nz_id,gfld3d_id,x_north_id,x_south_id,q_north_id,q_south_id
645 logical :: lbc
646 character(len=20) :: sdate
647 character(len=1024) :: record,filename
648 character(len=:),allocatable :: str
649 
650 ! Check field
651 call qg_fields_check(fld)
652 
653 ! Check whether the field should be invented or read from file
654 iread = 1
655 if (f_conf%has("read_from_file")) call f_conf%get_or_die("read_from_file",iread)
656 
657 if (iread==0) then
658  ! Invent field
659  call fckit_log%warning('qg_fields_read_file: inventing field')
660  call qg_fields_analytic_init(fld,f_conf,vdate)
661 else
662  ! Read field from file
663 
664  ! Get filename
665  call f_conf%get_or_die("filename",str)
666  call swap_name_member(f_conf, str)
667  filename = str
668  call fckit_log%info('qg_fields_read_file: opening '//trim(filename))
669 
670  ! Initialize field
671  call qg_fields_zero(fld)
672 
673  ! Open NetCDF file
674  call ncerr(nf90_open(trim(filename),nf90_nowrite,ncid))
675 
676  ! Get dimensions ids
677  call ncerr(nf90_inq_dimid(ncid,'nx',nx_id))
678  call ncerr(nf90_inq_dimid(ncid,'ny',ny_id))
679  call ncerr(nf90_inq_dimid(ncid,'nz',nz_id))
680 
681  ! Get dimensions
682  call ncerr(nf90_inquire_dimension(ncid,nx_id,len=nx))
683  call ncerr(nf90_inquire_dimension(ncid,ny_id,len=ny))
684  call ncerr(nf90_inquire_dimension(ncid,nz_id,len=nz))
685 
686  ! Test dimensions consistency with the field geometry
687  if ((nx/=fld%geom%nx).or.(ny/=fld%geom%ny).or.(nz/=fld%geom%nz)) then
688  write (record,*) 'qg_fields_read_file: input fields have wrong dimensions: ',nx,ny,nz
689  call fckit_log%error(record)
690  write (record,*) 'qg_fields_read_file: expected: ',fld%geom%nx,fld%geom%ny,fld%geom%nz
691  call fckit_log%error(record)
692  call abor1_ftn('qg_fields_read_file: input fields have wrong dimensions')
693  endif
694 
695  ! Get attributes
696  call ncerr(nf90_get_att(ncid,nf90_global,'bc',bc))
697  if (bc==0) then
698  lbc = .false.
699  elseif (bc==1) then
700  lbc = .true.
701  else
702  call abor1_ftn('qg_fields_read_file: wrong bc value')
703  end if
704  call ncerr(nf90_get_att(ncid,nf90_global,'sdate',sdate))
705 
706  ! Test attributes consistency with the field
707  if ((.not.lbc).and.fld%lbc) call abor1_ftn('qg_fields_read_file: LBC are missing in NetCDF file')
708 
709  ! Get variables ids
710  if (fld%lq) then
711  call ncerr(nf90_inq_varid(ncid,'q',gfld3d_id))
712  else
713  call ncerr(nf90_inq_varid(ncid,'x',gfld3d_id))
714  endif
715  if (fld%lbc) then
716  call ncerr(nf90_inq_varid(ncid,'x_north',x_north_id))
717  call ncerr(nf90_inq_varid(ncid,'x_south',x_south_id))
718  call ncerr(nf90_inq_varid(ncid,'q_north',q_north_id))
719  call ncerr(nf90_inq_varid(ncid,'q_south',q_south_id))
720  endif
721 
722  ! Get variables
723  call ncerr(nf90_get_var(ncid,gfld3d_id,fld%gfld3d))
724  if (fld%lbc) then
725  call ncerr(nf90_get_var(ncid,x_north_id,fld%x_north))
726  call ncerr(nf90_get_var(ncid,x_south_id,fld%x_south))
727  call ncerr(nf90_get_var(ncid,q_north_id,fld%q_north))
728  call ncerr(nf90_get_var(ncid,q_south_id,fld%q_south))
729  endif
730 
731  ! Close NetCDF file
732  call ncerr(nf90_close(ncid))
733 
734  ! Set date
735  call fckit_log%info('qg_fields_read_file: validity date is '//sdate)
736  call datetime_set(sdate,vdate)
737 end if
738 
739 ! Check field
740 call qg_fields_check(fld)
741 
742 end subroutine qg_fields_read_file
743 ! ------------------------------------------------------------------------------
744 !> Write fields to file
745 subroutine qg_fields_write_file(fld,f_conf,vdate)
746 
747 implicit none
748 
749 ! Passed variables
750 type(qg_fields),intent(in) :: fld !< Fields
751 type(fckit_configuration),intent(in) :: f_conf !< FCKIT configuration
752 type(datetime),intent(in) :: vdate !< Date and time
753 
754 ! Local variables
755 integer :: ncid,nx_id,ny_id,nz_id,lon_id,lat_id,z_id,area_id,heat_id,x_id,q_id,u_id,v_id
756 integer :: x_north_id,x_south_id,q_north_id,q_south_id
757 integer :: info
758 real(kind_real) :: x(fld%geom%nx,fld%geom%ny,fld%geom%nz),q(fld%geom%nx,fld%geom%ny,fld%geom%nz)
759 real(kind_real) :: u(fld%geom%nx,fld%geom%ny,fld%geom%nz),v(fld%geom%nx,fld%geom%ny,fld%geom%nz)
760 logical :: lwx,lwq,lwuv,ismpi,mainpe
761 character(len=20) :: sdate
762 character(len=1024) :: filename
763 
764 ! Check field
765 call qg_fields_check(fld)
766 
767 ! Compute streamfunction and potential vorticity
768 if (fld%lq) then
769  q = fld%gfld3d
770  lwq = .true.
771  if (fld%lbc) then
772  call convert_q_to_x(fld%geom,q,fld%x_north,fld%x_south,x)
773  lwx = .true.
774  else
775  lwx = .false.
776  endif
777 else
778  x = fld%gfld3d
779  lwx = .true.
780  if (fld%lbc) then
781  call convert_x_to_q(fld%geom,x,fld%x_north,fld%x_south,q)
782  lwq = .true.
783  else
784  lwq = .false.
785  endif
786 endif
787 
788 ! Compute wind
789 if (fld%lbc) then
790  call convert_x_to_uv(fld%geom,x,fld%x_north,fld%x_south,u,v)
791  lwuv = .true.
792 else
793  lwuv = .false.
794 endif
795 
796 ! Set filename
797 filename = genfilename(f_conf,800,vdate)
798 call fckit_log%info('qg_fields_write_file: writing '//trim(filename))
799 
800 ! Set date
801 call datetime_to_string(vdate,sdate)
802 
803 ! Create NetCDF file
804 call ncerr(nf90_create(trim(filename),or(nf90_clobber,nf90_64bit_offset),ncid))
805 
806 ! Define dimensions
807 call ncerr(nf90_def_dim(ncid,'nx',fld%geom%nx,nx_id))
808 call ncerr(nf90_def_dim(ncid,'ny',fld%geom%ny,ny_id))
809 call ncerr(nf90_def_dim(ncid,'nz',fld%geom%nz,nz_id))
810 
811 ! Define attributes
812 if (fld%lbc) then
813  call ncerr(nf90_put_att(ncid,nf90_global,'bc',1))
814 else
815  call ncerr(nf90_put_att(ncid,nf90_global,'bc',0))
816 end if
817 call ncerr(nf90_put_att(ncid,nf90_global,'sdate',sdate))
818 
819 ! Define variables
820 call ncerr(nf90_def_var(ncid,'lon',nf90_double,(/nx_id,ny_id/),lon_id))
821 call ncerr(nf90_def_var(ncid,'lat',nf90_double,(/nx_id,ny_id/),lat_id))
822 call ncerr(nf90_def_var(ncid,'z',nf90_double,(/nz_id/),z_id))
823 call ncerr(nf90_def_var(ncid,'area',nf90_double,(/nx_id,ny_id/),area_id))
824 call ncerr(nf90_def_var(ncid,'heat',nf90_double,(/nx_id,ny_id/),heat_id))
825 if (lwx) then
826  call ncerr(nf90_def_var(ncid,'x',nf90_double,(/nx_id,ny_id,nz_id/),x_id))
827  call ncerr(nf90_put_att(ncid,x_id,'_FillValue',missing_value(1.0_kind_real)))
828 endif
829 if (lwq) then
830  call ncerr(nf90_def_var(ncid,'q',nf90_double,(/nx_id,ny_id,nz_id/),q_id))
831  call ncerr(nf90_put_att(ncid,q_id,'_FillValue',missing_value(1.0_kind_real)))
832 endif
833 if (lwuv) then
834  call ncerr(nf90_def_var(ncid,'u',nf90_double,(/nx_id,ny_id,nz_id/),u_id))
835  call ncerr(nf90_put_att(ncid,u_id,'_FillValue',missing_value(1.0_kind_real)))
836  call ncerr(nf90_def_var(ncid,'v',nf90_double,(/nx_id,ny_id,nz_id/),v_id))
837  call ncerr(nf90_put_att(ncid,v_id,'_FillValue',missing_value(1.0_kind_real)))
838 endif
839 if (fld%lbc) then
840  call ncerr(nf90_def_var(ncid,'x_north',nf90_double,(/nz_id/),x_north_id))
841  call ncerr(nf90_put_att(ncid,x_north_id,'_FillValue',missing_value(1.0_kind_real)))
842  call ncerr(nf90_def_var(ncid,'x_south',nf90_double,(/nz_id/),x_south_id))
843  call ncerr(nf90_put_att(ncid,x_south_id,'_FillValue',missing_value(1.0_kind_real)))
844  call ncerr(nf90_def_var(ncid,'q_north',nf90_double,(/nx_id,nz_id/),q_north_id))
845  call ncerr(nf90_put_att(ncid,q_north_id,'_FillValue',missing_value(1.0_kind_real)))
846  call ncerr(nf90_def_var(ncid,'q_south',nf90_double,(/nx_id,nz_id/),q_south_id))
847  call ncerr(nf90_put_att(ncid,q_south_id,'_FillValue',missing_value(1.0_kind_real)))
848 end if
849 
850 ! End definitions
851 call ncerr(nf90_enddef(ncid))
852 
853 ! Put variables
854 call ncerr(nf90_put_var(ncid,lon_id,fld%geom%lon))
855 call ncerr(nf90_put_var(ncid,lat_id,fld%geom%lat))
856 call ncerr(nf90_put_var(ncid,z_id,fld%geom%z))
857 call ncerr(nf90_put_var(ncid,area_id,fld%geom%area))
858 call ncerr(nf90_put_var(ncid,heat_id,fld%geom%heat))
859 if (lwx) call ncerr(nf90_put_var(ncid,x_id,x))
860 if (lwq) call ncerr(nf90_put_var(ncid,q_id,q))
861 if (lwuv) then
862  call ncerr(nf90_put_var(ncid,u_id,u))
863  call ncerr(nf90_put_var(ncid,v_id,v))
864 endif
865 if (fld%lbc) then
866  call ncerr(nf90_put_var(ncid,x_north_id,fld%x_north))
867  call ncerr(nf90_put_var(ncid,x_south_id,fld%x_south))
868  call ncerr(nf90_put_var(ncid,q_north_id,fld%q_north))
869  call ncerr(nf90_put_var(ncid,q_south_id,fld%q_south))
870 endif
871 
872 ! Close NetCDF file
873 call ncerr(nf90_close(ncid))
874 
875 end subroutine qg_fields_write_file
876 ! ------------------------------------------------------------------------------
877 !> Analytic initialization of fields
878 subroutine qg_fields_analytic_init(fld,f_conf,vdate)
879 
880 implicit none
881 
882 ! Passed variables
883 type(qg_fields),intent(inout) :: fld !< Fields
884 type(fckit_configuration),intent(in) :: f_conf !< FCKIT configuration
885 type(datetime),intent(inout) :: vdate !< Date and time
886 
887 ! Local variables
888 integer :: ix,iy,iz
889 real(kind_real) :: uval
890 real(kind_real),allocatable :: x(:,:,:),q(:,:,:)
891 character(len=30) :: ic
892 character(len=20) :: sdate
893 character(len=:),allocatable :: str
894 
895 ! Check configuration
896 if (f_conf%has("analytic_init")) then
897  call f_conf%get_or_die("analytic_init",str)
898  ic = str
899 else
900  ic = 'baroclinic-instability'
901 endif
902 call fckit_log%warning('qg_fields_analytic_init: '//trim(ic))
903 
904 ! Set date
905 call f_conf%get_or_die("date",str)
906 sdate = str
907 call fckit_log%info('qg_fields_analytic_init: validity date is '//sdate)
908 call datetime_set(sdate,vdate)
909 
910 ! Check boundaries
911 if (.not.fld%lbc) call abor1_ftn('qg_fields_analytic_init: boundaries required')
912 
913 ! Allocation
914 allocate(x(fld%geom%nx,fld%geom%ny,fld%geom%nz))
915 allocate(q(fld%geom%nx,fld%geom%ny,fld%geom%nz))
916 
917 ! Define state
918 select case (trim(ic))
919 case ('baroclinic-instability')
920  ! Baroclinic instability
921  do iz=1,fld%geom%nz
922  do iy=1,fld%geom%ny
923  do ix=1,fld%geom%nx
924  call baroclinic_instability(fld%geom%x(ix),fld%geom%y(iy),fld%geom%z(iz),'x',x(ix,iy,iz))
925  enddo
926  enddo
927  call baroclinic_instability(0.0_kind_real,domain_meridional,fld%geom%z(iz),'x',fld%x_north(iz))
928  call baroclinic_instability(0.0_kind_real,0.0_kind_real,fld%geom%z(iz),'x',fld%x_south(iz))
929  end do
930 case ('large-vortices')
931  ! Large vortices
932  do iz=1,fld%geom%nz
933  do iy=1,fld%geom%ny
934  do ix=1,fld%geom%nx
935  call large_vortices(fld%geom%x(ix),fld%geom%y(iy),fld%geom%z(iz),'x',x(ix,iy,iz))
936  enddo
937  enddo
938  call large_vortices(0.0_kind_real,domain_meridional,fld%geom%z(iz),'x',fld%x_north(iz))
939  call large_vortices(0.0_kind_real,0.0_kind_real,fld%geom%z(iz),'x',fld%x_south(iz))
940  enddo
941 case ('uniform_field')
942  ! Uniform field
943  call f_conf%get_or_die("uval",uval)
944  x = uval
945 case default
946  call abor1_ftn ('qg_fields_analytic_init: unknown initialization')
947 end select
948 
949 ! Compute PV
950 call convert_x_to_q(fld%geom,x,fld%x_north,fld%x_south,q)
951 do iz=1,fld%geom%nz
952  do ix=1,fld%geom%nx
953  fld%q_south(ix,iz) = 2.0*q(ix,1,iz)-q(ix,2,iz)
954  enddo
955  do ix=1,fld%geom%nx
956  fld%q_north(ix,iz) = 2.0*q(ix,fld%geom%ny,iz)-q(ix,fld%geom%ny-1,iz)
957  enddo
958 end do
959 
960 ! Copy 3d field
961 if (fld%lq) then
962  fld%gfld3d = q
963 else
964  fld%gfld3d = x
965 endif
966 
967 ! Check field
968 call qg_fields_check(fld)
969 
970 end subroutine qg_fields_analytic_init
971 ! ------------------------------------------------------------------------------
972 !> Fields statistics
973 subroutine qg_fields_gpnorm(fld,nb,pstat)
974 
975 implicit none
976 
977 ! Passed variables
978 type(qg_fields),intent(in) :: fld !< Fields
979 integer,intent(in) :: nb !< Number of boundaries
980 real(kind_real),intent(inout) :: pstat(4*(1+nb)) !< Statistics
981 
982 ! Local variables
983 integer :: jj,js,jvb
984 real(kind_real) :: expo,stat(4,1+nb)
985 
986 ! Check field
987 call qg_fields_check(fld)
988 
989 ! Check number of stats
990 if ((fld%lbc.and.(nb/=2)).or.((.not.fld%lbc).and.(nb>0))) call abor1_ftn('qg_fields_gpnorm: error number of fields')
991 
992 ! 3d field
993 stat(2,1) = minval(fld%gfld3d)
994 stat(3,1) = maxval(fld%gfld3d)
995 stat(4,1) = sqrt(sum(fld%gfld3d**2)/real(fld%geom%nx*fld%geom%ny*fld%geom%nz,kind_real))
996 if (stat(4,1)>0.0) then
997  expo = aint(log(stat(4,1))/log(10.0_kind_real))
998  stat(1,1) = 10.0**expo
999 else
1000  stat(1,1) = 1.0
1001 endif
1002 stat(2:4,1) = stat(2:4,1)/stat(1,1)
1003 
1004 ! Boundaries
1005 if (nb==2) then
1006  ! Streamfunction
1007  stat(2,2) = min(minval(fld%x_north),minval(fld%x_south))
1008  stat(3,2) = max(maxval(fld%x_north),maxval(fld%x_south))
1009  stat(4,2) = sqrt(sum(fld%x_north**2+fld%x_south**2)/real(2*fld%geom%nz,kind_real))
1010  if (stat(4,2)>0.0) then
1011  expo = aint(log(stat(4,2))/log(10.0_kind_real))
1012  stat(1,2) = 10.0**expo
1013  else
1014  stat(1,2) = 1.0
1015  endif
1016  stat(2:4,2) = stat(2:4,2)/stat(1,2)
1017 
1018  ! Potential vorticity
1019  stat(2,3) = min(minval(fld%q_north),minval(fld%q_south))
1020  stat(3,3) = max(maxval(fld%q_north),maxval(fld%q_south))
1021  stat(4,3) = sqrt(sum(fld%q_north**2+fld%q_south**2)/real(2*fld%geom%nx*fld%geom%nz,kind_real))
1022  if (stat(4,3)>0.0) then
1023  expo = aint(log(stat(4,3))/log(10.0_kind_real))
1024  stat(1,3) = 10.0**expo
1025  else
1026  stat(1,3) = 1.0
1027  endif
1028  stat(2:4,3) = stat(2:4,3)/stat(1,3)
1029 endif
1030 
1031 ! Pack
1032 jj = 0
1033 do jvb=1,1+nb
1034  do js=1,4
1035  jj = jj+1
1036  pstat(jj) = stat(js,jvb)
1037  enddo
1038 enddo
1039 
1040 end subroutine qg_fields_gpnorm
1041 ! ------------------------------------------------------------------------------
1042 !> Fields RMS
1043 subroutine qg_fields_rms(fld,prms)
1044 
1045 implicit none
1046 
1047 ! Passed variables
1048 type(qg_fields),intent(in) :: fld !< Fields
1049 real(kind_real),intent(out) :: prms !< RMS
1050 
1051 ! Local variables
1052 integer :: norm
1053 real(kind_real) :: zz
1054 
1055 ! Check field
1056 call qg_fields_check(fld)
1057 
1058 ! 3d field
1059 zz = sum(fld%gfld3d**2)
1060 norm = fld%geom%nx*fld%geom%ny*fld%geom%nz
1061 
1062 ! Boundaries
1063 if (fld%lbc) then
1064  zz = zz+sum(fld%x_north**2+fld%x_south**2)+sum(fld%q_north**2+fld%q_south**2)
1065  norm = norm+2*(1+fld%geom%nx)*fld%geom%nz
1066 end if
1067 
1068 ! Normalize
1069 prms = sqrt(zz/real(norm,kind_real))
1070 
1071 end subroutine qg_fields_rms
1072 ! ------------------------------------------------------------------------------
1073 !> Get fields geometry
1074 subroutine qg_fields_sizes(fld,nx,ny,nz,nb)
1075 
1076 implicit none
1077 
1078 ! Passed variables
1079 type(qg_fields),intent(in) :: fld !< Fields
1080 integer,intent(out) :: nx !< X size
1081 integer,intent(out) :: ny !< Y size
1082 integer,intent(out) :: nz !< Z size
1083 integer,intent(out) :: nb !< Number of boundaries
1084 
1085 ! Copy sizes
1086 nx = fld%geom%nx
1087 ny = fld%geom%ny
1088 nz = fld%geom%nz
1089 if (fld%lbc) then
1090  ! North and South boundaries
1091  nb = 2
1092 else
1093  ! No boundaries
1094  nb = 0
1095 endif
1096 
1097 end subroutine qg_fields_sizes
1098 ! ------------------------------------------------------------------------------
1099 !> Get fields variables
1100 subroutine qg_fields_vars(fld,lq,lbc)
1101 
1102 implicit none
1103 
1104 ! Passed variables
1105 type(qg_fields),intent(in) :: fld !< Fields
1106 integer,intent(out) :: lq !< Potential vorticity flag
1107 integer,intent(out) :: lbc !< Boundaries flag
1108 
1109 ! Potential vorticity flag
1110 if (fld%lq) then
1111  lq = 1
1112 else
1113  lq = 0
1114 endif
1115 
1116 ! Boundaries flag
1117 if (fld%lbc) then
1118  lbc = 1
1119 else
1120  lbc = 0
1121 endif
1122 
1123 end subroutine qg_fields_vars
1124 ! ------------------------------------------------------------------------------
1125 !> Set ATLAS field
1126 subroutine qg_fields_set_atlas(self,vars,afieldset)
1127 
1128 implicit none
1129 
1130 ! Passed variables
1131 type(qg_fields),intent(in) :: self !< Fields
1132 type(oops_variables),intent(in) :: vars !< Variables
1133 type(atlas_fieldset),intent(inout) :: afieldset !< ATLAS fieldset
1134 
1135 ! Local variables
1136 character(len=1024) :: fieldname
1137 type(atlas_field) :: afield
1138 
1139 ! Get or create field
1140 if (vars%has('x')) fieldname = 'x'
1141 if (vars%has('q')) fieldname = 'q'
1142 if (afieldset%has_field(trim(fieldname))) then
1143  ! Get afield
1144  afield = afieldset%field(trim(fieldname))
1145 else
1146  ! Create field
1147  afield = self%geom%afunctionspace%create_field(name=trim(fieldname),kind=atlas_real(kind_real),levels=self%geom%nz)
1148 
1149  ! Add field
1150  call afieldset%add(afield)
1151 end if
1152 
1153 ! Release pointer
1154 call afield%final()
1155 
1156 end subroutine qg_fields_set_atlas
1157 ! ------------------------------------------------------------------------------
1158 !> Convert fields to ATLAS
1159 subroutine qg_fields_to_atlas(self,vars,afieldset)
1160 
1161 implicit none
1162 
1163 ! Passed variables
1164 type(qg_fields),intent(in) :: self !< Fields
1165 type(oops_variables),intent(in) :: vars !< Variables
1166 type(atlas_fieldset),intent(inout) :: afieldset !< ATLAS fieldset
1167 
1168 ! Local variables
1169 integer :: iv,ix,iy,iz,inode
1170 integer(kind_int),pointer :: int_ptr_1(:),int_ptr_2(:,:)
1171 real(kind_real) :: gfld3d(self%geom%nx,self%geom%ny,self%geom%nz)
1172 real(kind_real),pointer :: real_ptr_1(:),real_ptr_2(:,:)
1173 character(len=1024) :: fieldname
1174 type(atlas_field) :: afield
1175 
1176 ! Get variable
1177 if (vars%has('x')) then
1178  if (self%lq) then
1179  call convert_q_to_x(self%geom,self%gfld3d,self%x_north,self%x_south,gfld3d)
1180  else
1181  gfld3d = self%gfld3d
1182  end if
1183 end if
1184 if (vars%has('q')) then
1185  if (self%lq) then
1186  gfld3d = self%gfld3d
1187  else
1188  call convert_x_to_q(self%geom,self%gfld3d,self%x_north,self%x_south,gfld3d)
1189  end if
1190 end if
1191 
1192 ! Get or create field
1193 if (vars%has('x')) fieldname = 'x'
1194 if (vars%has('q')) fieldname = 'q'
1195 if (afieldset%has_field(trim(fieldname))) then
1196  ! Get afield
1197  afield = afieldset%field(trim(fieldname))
1198 else
1199  ! Create field
1200  afield = self%geom%afunctionspace%create_field(name=trim(fieldname),kind=atlas_real(kind_real),levels=self%geom%nz)
1201 
1202  ! Add field
1203  call afieldset%add(afield)
1204 end if
1205 
1206 ! Copy field
1207 call afield%data(real_ptr_2)
1208 do iz=1,self%geom%nz
1209  inode = 0
1210  do iy=1,self%geom%ny
1211  do ix=1,self%geom%nx
1212  inode = inode+1
1213  real_ptr_2(iz,inode) = gfld3d(ix,iy,iz)
1214  enddo
1215  enddo
1216 enddo
1217 
1218 ! Release pointer
1219 call afield%final()
1220 
1221 end subroutine qg_fields_to_atlas
1222 ! ------------------------------------------------------------------------------
1223 !> Get fields from ATLAS
1224 subroutine qg_fields_from_atlas(self,vars,afieldset)
1225 
1226 implicit none
1227 
1228 ! Passed variables
1229 type(qg_fields),intent(inout) :: self !< Fields
1230 type(oops_variables),intent(in) :: vars !< Variables
1231 type(atlas_fieldset),intent(inout) :: afieldset !< ATLAS fieldset
1232 
1233 ! Local variables
1234 integer :: ix,iy,iz,inode
1235 real(kind_real) :: gfld3d(self%geom%nx,self%geom%ny,self%geom%nz)
1236 real(kind_real),pointer :: real_ptr_1(:),real_ptr_2(:,:)
1237 character(len=1) :: cgrid
1238 character(len=1024) :: fieldname
1239 type(atlas_field) :: afield
1240 
1241 ! Get field
1242 if (vars%has('x')) fieldname = 'x'
1243 if (vars%has('q')) fieldname = 'q'
1244 afield = afieldset%field(trim(fieldname))
1245 
1246 ! Copy field
1247 call afield%data(real_ptr_2)
1248 do iz=1,self%geom%nz
1249  inode = 0
1250  do iy=1,self%geom%ny
1251  do ix=1,self%geom%nx
1252  inode = inode+1
1253  gfld3d(ix,iy,iz) = real_ptr_2(iz,inode)
1254  enddo
1255  enddo
1256 enddo
1257 
1258 ! Get variable
1259 if (vars%has('x')) then
1260  if (self%lq) then
1261  call convert_x_to_q(self%geom,gfld3d,self%x_north,self%x_south,self%gfld3d)
1262  else
1263  self%gfld3d = gfld3d
1264  end if
1265 end if
1266 if (vars%has('q')) then
1267  if (self%lq) then
1268  self%gfld3d = gfld3d
1269  else
1270  call convert_x_to_q(self%geom,gfld3d,self%x_north,self%x_south,self%gfld3d)
1271  end if
1272 end if
1273 
1274 ! Release pointer
1275 call afield%final()
1276 
1277 end subroutine qg_fields_from_atlas
1278 ! ------------------------------------------------------------------------------
1279 !> Get points from fields
1280 subroutine qg_fields_getpoint(fld,iter,nval,vals)
1281 
1282 implicit none
1283 
1284 ! Passed variables
1285 type(qg_fields),intent(in) :: fld !< Fields
1286 type(qg_geom_iter),intent(in) :: iter !< Geometry iterator
1287 integer,intent(in) :: nval !< Number of values
1288 real(kind_real),intent(inout) :: vals(nval) !< Values
1289 
1290 ! Local variables
1291 character(len=1024) :: record
1292 
1293 ! Check
1294 if ((fld%geom%nx/=iter%geom%nx).or.(fld%geom%ny/=iter%geom%ny).or.(fld%geom%nz/=iter%geom%nz)) then
1295  write(record,*) 'qg_fields_getpoint: resolution inconsistency, ',fld%geom%nx,'/',fld%geom%ny,'/',fld%geom%nz, &
1296 & ' and ',iter%geom%nx,'/',iter%geom%ny,'/',iter%geom%nz
1297  call abor1_ftn(record)
1298 endif
1299 if (fld%geom%nz/=nval) then
1300  write(record,*) 'qg_fields_getpoint: array sizes are different: ',fld%geom%nz,'/',nval
1301  call abor1_ftn(record)
1302 endif
1303 
1304 ! Get values
1305 vals = fld%gfld3d(iter%ilon,iter%ilat,:)
1306 
1307 end subroutine qg_fields_getpoint
1308 ! ------------------------------------------------------------------------------
1309 !> Set fields values at a specified gridpoint
1310 subroutine qg_fields_setpoint(fld,iter,nval,vals)
1311 
1312 implicit none
1313 
1314 ! Passed variables
1315 type(qg_fields),intent(inout) :: fld !< Fields
1316 type(qg_geom_iter),intent(in) :: iter !< Geometry iterator
1317 integer,intent(in) :: nval !< Number of values
1318 real(kind_real),intent(in) :: vals(nval) !< Values
1319 
1320 ! Local variables
1321 character(len=1024) :: record
1322 
1323 ! Check
1324 if ((fld%geom%nx/=iter%geom%nx).or.(fld%geom%ny/=iter%geom%ny).or.(fld%geom%nz/=iter%geom%nz)) then
1325  write(record,*) 'qg_fields_getpoint: resolution inconsistency,',fld%geom%nx,'/',fld%geom%ny,'/',fld%geom%nz, &
1326 & ' and ',iter%geom%nx,'/',iter%geom%ny,'/',iter%geom%nz
1327  call abor1_ftn(record)
1328 endif
1329 if (fld%geom%nz/=nval) then
1330  write(record,*) 'qg_fields_getpoint: array sizes are different:',fld%geom%nz,'/',nval
1331  call abor1_ftn(record)
1332 endif
1333 
1334 ! Set values
1335 fld%gfld3d(iter%ilon,iter%ilat,:) = vals
1336 
1337 end subroutine qg_fields_setpoint
1338 ! ------------------------------------------------------------------------------
1339 !> Serialize fields
1340 subroutine qg_fields_serialize(fld,vsize,vect_fld)
1341 
1342 implicit none
1343 
1344 ! Passed variables
1345 type(qg_fields),intent(in) :: fld !< Fields
1346 integer,intent(in) :: vsize !< Size
1347 real(kind_real),intent(inout) :: vect_fld(vsize) !< Vector
1348 
1349 ! Local variables
1350 integer :: ix,iy,iz,ind
1351 
1352 ! Initialize
1353 ind = 0
1354 
1355 ! Copy
1356 do iz = 1,fld%geom%nz
1357  do iy = 1,fld%geom%ny
1358  do ix = 1,fld%geom%nx
1359  ind = ind + 1
1360  vect_fld(ind) = fld%gfld3d(ix,iy,iz)
1361  enddo
1362  enddo
1363 enddo
1364 
1365 if (fld%lbc) then
1366  do iz=1,fld%geom%nz
1367  ind = ind + 1
1368  vect_fld(ind) = fld%x_north(iz)
1369  ind = ind + 1
1370  vect_fld(ind) = fld%x_south(iz)
1371  do ix=1,fld%geom%nx
1372  ind = ind + 1
1373  vect_fld(ind) = fld%q_north(ix,iz)
1374  ind = ind + 1
1375  vect_fld(ind) = fld%q_south(ix,iz)
1376  enddo
1377  enddo
1378 endif
1379 
1380 end subroutine qg_fields_serialize
1381 ! ------------------------------------------------------------------------------
1382 !> Deserialize fields
1383 subroutine qg_fields_deserialize(self,vsize,vect_fld,index)
1384 
1385 implicit none
1386 
1387 ! Passed variables
1388 type(qg_fields),intent(inout) :: self !< Fields
1389 integer,intent(in) :: vsize !< Size
1390 real(kind_real),intent(in) :: vect_fld(vsize) !< Vector
1391 integer,intent(inout) :: index !< Index
1392 
1393 ! Local variables
1394 integer :: ix,iy,iz
1395 
1396 ! 3d field
1397 index = 1 + index
1398 do iz = 1,self%geom%nz
1399  do iy = 1,self%geom%ny
1400  do ix = 1,self%geom%nx
1401  self%gfld3d(ix,iy,iz) = vect_fld(index)
1402  index = index+1
1403  enddo
1404  enddo
1405 enddo
1406 
1407 ! Boundaries
1408 if (self%lbc) then
1409  do iz=1,self%geom%nz
1410  index = index + 1
1411  self%x_north(iz) = vect_fld(index)
1412  index = index + 1
1413  self%x_south(iz) = vect_fld(index)
1414  do ix=1,self%geom%nx
1415  index = index + 1
1416  self%q_north(ix,iz) = vect_fld(index)
1417  index = index + 1
1418  self%q_south(ix,iz) = vect_fld(index)
1419  enddo
1420  enddo
1421 endif
1422 
1423 index = index - 1
1424 
1425 end subroutine qg_fields_deserialize
1426 ! ------------------------------------------------------------------------------
1427 !> Check fields
1428 subroutine qg_fields_check(self)
1429 
1430 implicit none
1431 
1432 ! Passed variables
1433 type(qg_fields),intent(in) :: self !< Fields
1434 
1435 ! Local variables
1436 logical :: bad
1437 character(len=1024) :: record
1438 
1439 ! Initialization
1440 bad = .false.
1441 
1442 ! Check 3d field
1443 bad = bad.or.(.not.allocated(self%gfld3d))
1444 bad = bad.or.(size(self%gfld3d,1)/=self%geom%nx)
1445 bad = bad.or.(size(self%gfld3d,2)/=self%geom%ny)
1446 bad = bad.or.(size(self%gfld3d,3)/=self%geom%nz)
1447 
1448 ! Check boundaries
1449 if (self%lbc) then
1450  bad = bad.or.(.not.allocated(self%x_north))
1451  bad = bad.or.(.not.allocated(self%x_south))
1452  bad = bad.or.(.not.allocated(self%q_north))
1453  bad = bad.or.(.not.allocated(self%q_south))
1454  bad = bad.or.(size(self%x_north)/=self%geom%nz)
1455  bad = bad.or.(size(self%x_south)/=self%geom%nz)
1456  bad = bad.or.(size(self%q_north,1)/=self%geom%nx)
1457  bad = bad.or.(size(self%q_north,2)/=self%geom%nz)
1458  bad = bad.or.(size(self%q_south,1)/=self%geom%nx)
1459  bad = bad.or.(size(self%q_south,2)/=self%geom%nz)
1460 else
1461  bad = bad.or.allocated(self%x_north)
1462  bad = bad.or.allocated(self%x_south)
1463  bad = bad.or.allocated(self%q_north)
1464  bad = bad.or.allocated(self%q_south)
1465 endif
1466 
1467 if (bad) then
1468  call fckit_log%info('qg_fields_check: field not consistent')
1469  write(record,*) ' nx,ny,nz,lbc = ',self%geom%nx,self%geom%ny,self%geom%nz,self%lbc
1470  call fckit_log%info(record)
1471  write(record,*) ' shape(gfld3d) = ',shape(self%gfld3d)
1472  call fckit_log%info(record)
1473  if (self%lbc) then
1474  write(record,*) ' shape(x_north) = ',shape(self%x_north)
1475  call fckit_log%info(record)
1476  write(record,*) ' shape(x_south) = ',shape(self%x_south)
1477  call fckit_log%info(record)
1478  write(record,*) ' shape(q_north) = ',shape(self%q_north)
1479  call fckit_log%info(record)
1480  write(record,*) ' shape(q_south) = ',shape(self%q_south)
1481  call fckit_log%info(record)
1482  call abor1_ftn ('qg_fields_check: field not consistent')
1483  endif
1484 endif
1485 
1486 end subroutine qg_fields_check
1487 ! ------------------------------------------------------------------------------
1488 !> Check fields resolution
1489 subroutine qg_fields_check_resolution(fld1,fld2)
1490 
1491 implicit none
1492 
1493 ! Passed variables
1494 type(qg_fields),intent(in) :: fld1 !< First fields
1495 type(qg_fields),intent(in) :: fld2 !< Second fields
1496 
1497 ! Local variables
1498 character(len=1024) :: record
1499 
1500 ! Check fields consistency
1501 if ((fld1%geom%nx/=fld2%geom%nx).or.(fld1%geom%ny/=fld2%geom%ny).or.(fld1%geom%nz/=fld2%geom%nz)) then
1502  write(record,*) 'qg_fields_check_resolution: resolution inconsistency, ',fld1%geom%nx,'/',fld1%geom%ny,'/',fld1%geom%nz, &
1503 & ' and ',fld2%geom%nx,'/',fld2%geom%ny,'/',fld2%geom%nz
1504  call abor1_ftn(record)
1505 endif
1506 
1507 ! Check fields independently
1508 call qg_fields_check(fld1)
1509 call qg_fields_check(fld2)
1510 
1511 end subroutine qg_fields_check_resolution
1512 ! ------------------------------------------------------------------------------
1513 !> Check fields variables
1514 subroutine qg_fields_check_variables(fld1,fld2)
1515 
1516 implicit none
1517 
1518 ! Passed variables
1519 type(qg_fields),intent(in) :: fld1 !< First fields
1520 type(qg_fields),intent(in) :: fld2 !< Second fields
1521 
1522 ! Local variables
1523 character(len=1024) :: record
1524 
1525 ! Check fields consistency
1526 if (fld1%lq.neqv.fld2%lq) then
1527  write(record,*) 'qg_fields_check_variables: variables inconsistency, ',fld1%lq,' and ',fld2%lq
1528  call abor1_ftn(record)
1529 endif
1530 
1531 ! Check fields independently
1532 call qg_fields_check(fld1)
1533 call qg_fields_check(fld2)
1534 
1535 end subroutine qg_fields_check_variables
1536 ! ------------------------------------------------------------------------------
1537 end module qg_fields_mod
qg_fields_mod
Definition: qg_fields_mod.F90:9
qg_fields_mod::qg_fields_rms
subroutine, public qg_fields_rms(fld, prms)
Fields RMS.
Definition: qg_fields_mod.F90:1044
qg_fields_mod::qg_fields
Definition: qg_fields_mod.F90:51
qg_geom_mod
Definition: qg_geom_mod.F90:9
qg_fields_mod::qg_fields_read_file
subroutine, public qg_fields_read_file(fld, f_conf, vdate)
Read fields from file.
Definition: qg_fields_mod.F90:633
qg_convert_x_to_q_mod
Definition: qg_convert_x_to_q_mod.F90:9
qg_fields_mod::qg_fields_axpy
subroutine, public qg_fields_axpy(self, zz, rhs)
Apply axpy operator to fields.
Definition: qg_fields_mod.F90:436
qg_fields_mod::qg_fields_sizes
subroutine, public qg_fields_sizes(fld, nx, ny, nz, nb)
Get fields geometry.
Definition: qg_fields_mod.F90:1075
qg_tools_mod::large_vortices
subroutine, public large_vortices(x, y, z, var, res)
Generate values for large vortices.
Definition: qg_tools_mod.F90:148
qg_fields_mod::qg_fields_ones
subroutine, public qg_fields_ones(self)
Set fields to ones.
Definition: qg_fields_mod.F90:240
qg_fields_mod::qg_fields_check_resolution
subroutine, public qg_fields_check_resolution(fld1, fld2)
Check fields resolution.
Definition: qg_fields_mod.F90:1490
qg_fields_mod::qg_fields_set_atlas
subroutine, public qg_fields_set_atlas(self, vars, afieldset)
Set ATLAS field.
Definition: qg_fields_mod.F90:1127
qg_fields_mod::qg_fields_dot_prod
subroutine, public qg_fields_dot_prod(fld1, fld2, zprod)
Compute dot product for fields.
Definition: qg_fields_mod.F90:485
qg_fields_mod::qg_fields_write_file
subroutine, public qg_fields_write_file(fld, f_conf, vdate)
Write fields to file.
Definition: qg_fields_mod.F90:746
qg_tools_mod::genfilename
character(len=2 *length) function, public genfilename(f_conf, length, vdate)
Generate filename.
Definition: qg_tools_mod.F90:31
qg_fields_mod::qg_fields_zero
subroutine, public qg_fields_zero(self)
Set fields to zero.
Definition: qg_fields_mod.F90:218
qg_interp_mod::qg_interp_trilinear
subroutine, public qg_interp_trilinear(geom, lon, lat, z, gfld3d, val)
Trilinear interpolation.
Definition: qg_interp_mod.F90:29
qg_fields_mod::rseed
integer, parameter rseed
Random seed (for reproducibility)
Definition: qg_fields_mod.F90:49
qg_fields_mod::qg_fields_check_variables
subroutine, public qg_fields_check_variables(fld1, fld2)
Check fields variables.
Definition: qg_fields_mod.F90:1515
qg_fields_mod::qg_fields_self_schur
subroutine, public qg_fields_self_schur(self, rhs)
Schur product of fields.
Definition: qg_fields_mod.F90:461
qg_fields_mod::qg_fields_vars
subroutine, public qg_fields_vars(fld, lq, lbc)
Get fields variables.
Definition: qg_fields_mod.F90:1101
qg_fields_mod::qg_fields_create
subroutine, public qg_fields_create(self, geom, vars, lbc)
Linked list implementation.
Definition: qg_fields_mod.F90:79
qg_geom_mod::qg_geom
Definition: qg_geom_mod.F90:26
oops_variables_mod
Fortran interface to Variables.
Definition: variables_mod.F90:9
qg_convert_q_to_x_mod
Definition: qg_convert_q_to_x_mod.F90:9
qg_locs_mod
Definition: qg_locs_mod.F90:9
qg_fields_mod::qg_fields_from_atlas
subroutine, public qg_fields_from_atlas(self, vars, afieldset)
Get fields from ATLAS.
Definition: qg_fields_mod.F90:1225
qg_fields_mod::qg_fields_analytic_init
subroutine, public qg_fields_analytic_init(fld, f_conf, vdate)
Analytic initialization of fields.
Definition: qg_fields_mod.F90:879
qg_fields_mod::qg_fields_self_add
subroutine, public qg_fields_self_add(self, rhs)
Add fields.
Definition: qg_fields_mod.F90:365
qg_fields_mod::qg_fields_diff_incr
subroutine, public qg_fields_diff_incr(lhs, fld1, fld2)
Compute increment from the difference of two fields.
Definition: qg_fields_mod.F90:531
qg_interp_mod
Definition: qg_interp_mod.F90:9
qg_constants_mod
Definition: qg_constants_mod.F90:9
qg_fields_mod::qg_fields_gpnorm
subroutine, public qg_fields_gpnorm(fld, nb, pstat)
Fields statistics.
Definition: qg_fields_mod.F90:974
qg_fields_mod::qg_fields_self_mul
subroutine, public qg_fields_self_mul(self, zz)
Multiply fields by a scalar.
Definition: qg_fields_mod.F90:413
qg_convert_x_to_q_mod::convert_x_to_q
subroutine, public convert_x_to_q(geom, x, x_north, x_south, q)
Convert streamfunction to potential vorticity.
Definition: qg_convert_x_to_q_mod.F90:25
qg_convert_x_to_uv_mod::convert_x_to_uv
subroutine, public convert_x_to_uv(geom, x, x_north, x_south, u, v)
Convert streafunction to wind components.
Definition: qg_convert_x_to_uv_mod.F90:23
qg_fields_mod::qg_fields_serialize
subroutine, public qg_fields_serialize(fld, vsize, vect_fld)
Serialize fields.
Definition: qg_fields_mod.F90:1341
qg_fields_mod::qg_fields_setpoint
subroutine, public qg_fields_setpoint(fld, iter, nval, vals)
Set fields values at a specified gridpoint.
Definition: qg_fields_mod.F90:1311
qg_fields_mod::qg_fields_getpoint
subroutine, public qg_fields_getpoint(fld, iter, nval, vals)
Get points from fields.
Definition: qg_fields_mod.F90:1281
qg_fields_mod::qg_fields_self_sub
subroutine, public qg_fields_self_sub(self, rhs)
Subtract fields.
Definition: qg_fields_mod.F90:389
qg_tools_mod::baroclinic_instability
subroutine, public baroclinic_instability(x, y, z, var, res)
Generate values for baroclinic instability.
Definition: qg_tools_mod.F90:112
qg_fields_mod::qg_fields_create_from_other
subroutine, public qg_fields_create_from_other(self, other)
Create fields from another one.
Definition: qg_fields_mod.F90:168
qg_convert_x_to_uv_mod
Definition: qg_convert_x_to_uv_mod.F90:9
oops_variables_mod::oops_variables
Definition: variables_mod.F90:16
qg_geom_iter_mod::qg_geom_iter
Definition: qg_geom_iter_mod.F90:22
qg_geom_iter_mod
Definition: qg_geom_iter_mod.F90:9
qg_fields_mod::qg_fields_check
subroutine, public qg_fields_check(self)
Check fields.
Definition: qg_fields_mod.F90:1429
qg_fields_mod::qg_fields_random
subroutine, public qg_fields_random(self)
Generate random fields.
Definition: qg_fields_mod.F90:305
qg_tools_mod
Definition: qg_tools_mod.F90:9
qg_gom_mod
Definition: qg_gom_mod.F90:9
qg_fields_mod::qg_fields_add_incr
subroutine, public qg_fields_add_incr(self, rhs)
Add increment to fields.
Definition: qg_fields_mod.F90:504
qg_fields_mod::qg_fields_deserialize
subroutine, public qg_fields_deserialize(self, vsize, vect_fld, index)
Deserialize fields.
Definition: qg_fields_mod.F90:1384
qg_fields_mod::qg_fields_registry
type(registry_t), public qg_fields_registry
Linked list interface - defines registry_t type.
Definition: qg_fields_mod.F90:68
qg_tools_mod::ncerr
subroutine, public ncerr(info)
Check NetCDF status.
Definition: qg_tools_mod.F90:99
qg_convert_q_to_x_mod::convert_q_to_x
subroutine, public convert_q_to_x(geom, q, x_north, x_south, x)
Convert potential vorticity to streamfunction.
Definition: qg_convert_q_to_x_mod.F90:25
qg_fields_mod::qg_fields_copy
subroutine, public qg_fields_copy(self, other, bconly)
Copy fields.
Definition: qg_fields_mod.F90:321
qg_fields_mod::qg_fields_dirac
subroutine, public qg_fields_dirac(self, f_conf)
Set fields to Diracs.
Definition: qg_fields_mod.F90:262
qg_constants_mod::domain_meridional
real(kind_real), parameter, public domain_meridional
Model domain in meridional direction (m)
Definition: qg_constants_mod.F90:33
qg_fields_mod::qg_fields_to_atlas
subroutine, public qg_fields_to_atlas(self, vars, afieldset)
Convert fields to ATLAS.
Definition: qg_fields_mod.F90:1160
qg_fields_mod::qg_fields_change_resol
subroutine, public qg_fields_change_resol(fld, rhs)
Change fields resolution.
Definition: qg_fields_mod.F90:563
qg_fields_mod::qg_fields_delete
subroutine, public qg_fields_delete(self)
Delete fields.
Definition: qg_fields_mod.F90:201
qg_fields_mod::qg_fields_create_default
subroutine, public qg_fields_create_default(self, geom, lbc)
Create fields from geometry (x)
Definition: qg_fields_mod.F90:129