43 real(kind=kind_real),
pointer :: gfld3d(:,:,:)
44 real(kind=kind_real),
pointer :: x(:,:,:)
45 real(kind=kind_real),
pointer :: q(:,:,:)
46 real(kind=kind_real),
pointer :: u(:,:,:)
47 real(kind=kind_real),
pointer :: v(:,:,:)
48 real(kind=kind_real),
pointer :: xbound(:)
49 real(kind=kind_real),
pointer :: x_north(:)
50 real(kind=kind_real),
pointer :: x_south(:)
51 real(kind=kind_real),
pointer :: qbound(:,:)
52 real(kind=kind_real),
pointer :: q_north(:,:)
53 real(kind=kind_real),
pointer :: q_south(:,:)
54 character(len=1),
allocatable :: fldnames(:)
59 #define LISTED_TYPE qg_field 62 #include "oops/util/linkedList_i.f" 71 #include "oops/util/linkedList_c.f" 75 subroutine create(self, geom, vars)
77 type(
qg_field),
intent(inout) :: self
78 type(
qg_geom),
target,
intent(in) :: geom
79 type(
qg_vars),
intent(in) :: vars
87 allocate(self%gfld3d(self%geom%nx,self%geom%ny,self%nl*self%nf))
88 self%gfld3d(:,:,:)=0.0_kind_real
91 self%x => self%gfld3d(:,:,ioff+1:ioff+self%nl)
95 self%q => self%gfld3d(:,:,ioff+1:ioff+self%nl)
97 self%u => self%gfld3d(:,:,ioff+1:ioff+self%nl)
99 self%v => self%gfld3d(:,:,ioff+1:ioff+self%nl)
106 if (ioff/=self%nf*self%nl)
call abor1_ftn (
"qg_fields:create error number of fields")
108 allocate(self%fldnames(self%nf))
109 self%fldnames(:)=vars%fldnames(:)
112 allocate(self%xbound(4))
113 self%xbound(:)=0.0_kind_real
114 self%x_north => self%xbound(1:2)
115 self%x_south => self%xbound(3:4)
116 allocate(self%qbound(self%geom%nx,4))
117 self%qbound(:,:)=0.0_kind_real
118 self%q_north => self%qbound(:,1:2)
119 self%q_south => self%qbound(:,3:4)
121 self%xbound => null()
122 self%x_north => null()
123 self%x_south => null()
124 self%qbound => null()
125 self%q_north => null()
126 self%q_south => null()
137 type(
qg_field),
intent(inout) :: self
141 if (
associated(self%gfld3d))
deallocate(self%gfld3d)
142 if (
associated(self%xbound))
deallocate(self%xbound)
143 if (
associated(self%qbound))
deallocate(self%qbound)
144 if (
allocated(self%fldnames))
deallocate(self%fldnames)
150 subroutine zeros(self)
152 type(
qg_field),
intent(inout) :: self
156 self%gfld3d(:,:,:) = 0.0_kind_real
158 self%xbound(:) = 0.0_kind_real
159 self%qbound(:,:) = 0.0_kind_real
166 subroutine dirac(self, c_conf)
169 type(
qg_field),
intent(inout) :: self
170 type(c_ptr),
intent(in) :: c_conf
171 integer :: ndir,idir,ildir,ifdir,ioff
172 integer,
allocatable :: ixdir(:),iydir(:)
173 character(len=3) :: idirchar
178 ndir = config_get_int(c_conf,
"ndir")
179 allocate(ixdir(ndir))
180 allocate(iydir(ndir))
182 write(idirchar,
'(i3)') idir
183 ixdir(idir) = config_get_int(c_conf,
"ixdir("//trim(adjustl(idirchar))//
")")
184 iydir(idir) = config_get_int(c_conf,
"iydir("//trim(adjustl(idirchar))//
")")
186 ildir = config_get_int(c_conf,
"ildir")
187 ifdir = config_get_int(c_conf,
"ifdir")
190 if (ndir<1)
call abor1_ftn(
"qg_fields:dirac non-positive ndir")
191 if (any(ixdir<1).or.any(ixdir>self%geom%nx))
call abor1_ftn(
"qg_fields:dirac invalid ixdir")
192 if (any(iydir<1).or.any(iydir>self%geom%ny))
call abor1_ftn(
"qg_fields:dirac invalid iydir")
193 if ((ildir<1).or.(ildir>self%nl))
call abor1_ftn(
"qg_fields:dirac invalid ildir")
194 if ((ifdir<1).or.(ifdir>self%nf))
call abor1_ftn(
"qg_fields:dirac invalid ifdir")
198 ioff = (ifdir-1)*self%nl
200 self%gfld3d(ixdir(idir),iydir(idir),ioff+ildir) = 1.0
210 type(
qg_field),
intent(inout) :: self
224 subroutine copy(self,rhs)
226 type(
qg_field),
intent(inout) :: self
233 self%gfld3d(:,:,1:nf) = rhs%gfld3d(:,:,1:nf)
234 if (self%nf>nf) self%gfld3d(:,:,nf+1:self%nf) = 0.0_kind_real
238 self%xbound(:) = rhs%xbound(:)
239 self%qbound(:,:) = rhs%qbound(:,:)
241 self%xbound(:) = 0.0_kind_real
242 self%qbound(:,:) = 0.0_kind_real
253 type(
qg_field),
intent(inout) :: self
260 self%gfld3d(:,:,1:nf) = self%gfld3d(:,:,1:nf) + rhs%gfld3d(:,:,1:nf)
262 if (self%lbc .and. rhs%lbc)
then 263 self%xbound(:) = self%xbound(:) + rhs%xbound(:)
264 self%qbound(:,:) = self%qbound(:,:) + rhs%qbound(:,:)
274 type(
qg_field),
intent(inout) :: self
281 self%gfld3d(:,:,1:nf) = self%gfld3d(:,:,1:nf) * rhs%gfld3d(:,:,1:nf)
283 if (self%lbc .and. rhs%lbc)
then 284 self%xbound(:) = self%xbound(:) * rhs%xbound(:)
285 self%qbound(:,:) = self%qbound(:,:) * rhs%qbound(:,:)
295 type(
qg_field),
intent(inout) :: self
302 self%gfld3d(:,:,1:nf) = self%gfld3d(:,:,1:nf) - rhs%gfld3d(:,:,1:nf)
304 if (self%lbc .and. rhs%lbc)
then 305 self%xbound(:) = self%xbound(:) - rhs%xbound(:)
306 self%qbound(:,:) = self%qbound(:,:) - rhs%qbound(:,:)
316 type(
qg_field),
intent(inout) :: self
317 real(kind=kind_real),
intent(in) :: zz
321 self%gfld3d(:,:,:) = zz * self%gfld3d(:,:,:)
323 self%xbound(:) = zz * self%xbound(:)
324 self%qbound(:,:) = zz * self%qbound(:,:)
332 subroutine axpy(self,zz,rhs)
334 type(
qg_field),
intent(inout) :: self
335 real(kind=kind_real),
intent(in) :: zz
342 self%gfld3d(:,:,1:nf) = self%gfld3d(:,:,1:nf) + zz * rhs%gfld3d(:,:,1:nf)
344 if (self%lbc .and. rhs%lbc)
then 345 self%xbound(:) = self%xbound(:) + zz * rhs%xbound(:)
346 self%qbound(:,:) = self%qbound(:,:) + zz * rhs%qbound(:,:)
354 subroutine dot_prod(fld1,fld2,zprod)
356 type(
qg_field),
intent(in) :: fld1, fld2
357 real(kind=kind_real),
intent(inout) :: zprod
359 integer :: jx,jy,jz,jj
360 real(kind=kind_real),
allocatable :: zz(:)
363 if (fld1%nf /= fld2%nf .or. fld1%nl /= fld2%nl)
then 364 call abor1_ftn(
"qg_fields:field_prod error number of fields")
370 allocate(zz(fld1%nl*fld1%nf))
374 do jz=1,fld1%nl*fld1%nf
375 zz(jz) = zz(jz) + fld1%gfld3d(jx,jy,jz) * fld2%gfld3d(jx,jy,jz)
381 do jj=1,fld1%nl*fld1%nf
393 type(
qg_field),
intent(inout) :: self
401 if (self%geom%nx==rhs%geom%nx .and. self%geom%ny==rhs%geom%ny)
then 403 select case (trim(rhs%fldnames(i)))
405 self%x(:,:,:) = self%x(:,:,:) + rhs%x(:,:,:)
407 self%q(:,:,:) = self%q(:,:,:) + rhs%q(:,:,:)
409 self%u(:,:,:) = self%u(:,:,:) + rhs%u(:,:,:)
411 self%v(:,:,:) = self%v(:,:,:) + rhs%v(:,:,:)
415 call abor1_ftn(
"qg_fields:add_incr: not coded for low res increment yet")
425 type(
qg_field),
intent(inout) :: lhs
436 if (x1%geom%nx==x2%geom%nx .and. x1%geom%ny==x2%geom%ny)
then 437 if (lhs%geom%nx==x1%geom%nx .and. lhs%geom%ny==x1%geom%ny)
then 439 select case (trim(lhs%fldnames(i)))
441 lhs%x(:,:,:) = x1%x(:,:,:) - x2%x(:,:,:)
443 lhs%q(:,:,:) = x1%q(:,:,:) - x2%q(:,:,:)
445 lhs%u(:,:,:) = x1%u(:,:,:) - x2%u(:,:,:)
447 lhs%v(:,:,:) = x1%v(:,:,:) - x2%v(:,:,:)
451 call abor1_ftn(
"qg_fields:diff_incr: not coded for low res increment yet")
454 call abor1_ftn(
"qg_fields:diff_incr: states not at same resolution")
464 type(
qg_field),
intent(inout) :: fld
466 real(kind=kind_real),
allocatable :: ztmp(:,:)
467 real(kind=kind_real) :: dy1, dy2, ya, yb, dx1, dx2, xa, xb
468 integer :: jx, jy, jf, iy, ia, ib
473 if (fld%geom%nx==rhs%geom%nx .and. fld%geom%ny==rhs%geom%ny)
then 476 call abor1_ftn(
"qg_fields:field_resol: untested code")
478 allocate(ztmp(rhs%geom%nx,rhs%nl*rhs%nf))
479 dy1=1.0_kind_real/
real(fld%geom%ny,
kind_real)
480 dy2=1.0_kind_real/
real(rhs%geom%ny,
kind_real)
481 dx1=1.0_kind_real/
real(fld%geom%nx,
kind_real)
482 dx2=1.0_kind_real/
real(rhs%geom%nx,
kind_real)
485 if (jy==1 .or. jy==fld%geom%ny)
then 492 do jf=1,rhs%nl*rhs%nf
493 ztmp(jx,jf)=rhs%gfld3d(jx,iy,jf)
498 if (ib>rhs%geom%ny)
call abor1_ftn(
"qg_fields:field_resol: ib too large")
500 do jf=1,rhs%nl*rhs%nf
501 ztmp(jx,jf)=ya*rhs%gfld3d(jx,ia,jf)+yb*rhs%gfld3d(jx,ib,jf)
508 if (ib>rhs%geom%nx) ib=ib-rhs%geom%nx
509 do jf=1,fld%nl*rhs%nf
510 fld%gfld3d(jx,jy,jf)=xa*ztmp(jx,jf)+xb*ztmp(jx+1,jf)
527 use fckit_log_module,
only : fckit_log
530 type(
qg_field),
intent(inout) :: fld
531 type(c_ptr),
intent(in) :: c_conf
532 type(datetime),
intent(inout) :: vdate
534 integer,
parameter :: iunit=10
535 integer,
parameter :: max_string_length=800
536 character(len=max_string_length+50) :: record
537 character(len=max_string_length) :: filename
538 character(len=20) :: sdate, fmtn
539 character(len=4) :: cnx
540 character(len=11) :: fmt1=
'(X,ES24.16)' 541 character(len=1024) :: buf
542 integer :: ic, iy, il, ix, is, jx, jy, jf, iread, nf
543 integer :: ncid, nx_id, ny_id, nl_id, nc_id, gfld3d_id, xbound_id, qbound_id
544 real(kind=kind_real),
allocatable :: zz(:)
547 if (config_element_exists(c_conf,
"read_from_file"))
then 548 iread = config_get_int(c_conf,
"read_from_file")
551 call fckit_log%warning(
"qg_fields:read_file: Inventing State")
553 sdate = config_get_string(c_conf,len(sdate),
"date")
554 write(buf,*)
'validity date is: '//sdate
555 call fckit_log%info(buf)
556 call datetime_set(sdate, vdate)
559 filename = config_get_string(c_conf,len(filename),
"filename")
560 write(buf,*)
'qg_field:read_file: opening '//filename
561 call fckit_log%info(buf)
566 call ncerr(nf90_open(trim(filename)//
'.nc',nf90_nowrite,ncid))
567 call ncerr(nf90_inq_dimid(ncid,
'nx',nx_id))
568 call ncerr(nf90_inq_dimid(ncid,
'ny',ny_id))
569 call ncerr(nf90_inq_dimid(ncid,
'nl',nl_id))
570 call ncerr(nf90_inq_dimid(ncid,
'nc',nc_id))
571 call ncerr(nf90_inquire_dimension(ncid,nx_id,len=ix))
572 call ncerr(nf90_inquire_dimension(ncid,ny_id,len=iy))
573 call ncerr(nf90_inquire_dimension(ncid,nl_id,len=il))
574 call ncerr(nf90_inquire_dimension(ncid,nc_id,len=ic))
575 if (ix /= fld%geom%nx .or. iy /= fld%geom%ny .or. il /= fld%nl)
then 576 write (record,*)
"qg_fields:read_file: ", &
577 &
"input fields have wrong dimensions: ",ix,iy,il
578 call fckit_log%error(record)
579 write (record,*)
"qg_fields:read_file: expected: ",fld%geom%nx,fld%geom%ny,fld%nl
580 call fckit_log%error(record)
581 call abor1_ftn(
"qg_fields:read_file: input fields have wrong dimensions")
583 call ncerr(nf90_get_att(ncid,nf90_global,
'lbc',is))
584 call ncerr(nf90_get_att(ncid,nf90_global,
'sdate',sdate))
585 write(buf,*)
'validity date is: '//sdate
586 call fckit_log%info(buf)
588 call ncerr(nf90_inq_varid(ncid,
'gfld3d',gfld3d_id))
590 call ncerr(nf90_get_var(ncid,gfld3d_id,fld%gfld3d(:,:,jf),(/1,1,jf/),(/ix,iy,1/)))
593 call ncerr(nf90_inq_varid(ncid,
'xbound',xbound_id))
594 call ncerr(nf90_get_var(ncid,xbound_id,fld%xbound))
595 call ncerr(nf90_inq_varid(ncid,
'qbound',qbound_id))
596 call ncerr(nf90_get_var(ncid,qbound_id,fld%qbound))
598 call ncerr(nf90_close(ncid))
602 open(unit=iunit, file=trim(filename), form=
'formatted', action=
'read')
604 read(iunit,*) ix, iy, il, ic, is
605 if (ix /= fld%geom%nx .or. iy /= fld%geom%ny .or. il /= fld%nl)
then 606 write (record,*)
"qg_fields:read_file: ", &
607 &
"input fields have wrong dimensions: ",ix,iy,il
608 call fckit_log%error(record)
609 write (record,*)
"qg_fields:read_file: expected: ",fld%geom%nx,fld%geom%ny,fld%nl
610 call fckit_log%error(record)
611 call abor1_ftn(
"qg_fields:read_file: input fields have wrong dimensions")
615 write(buf,*)
'validity date is: '//sdate
616 call fckit_log%info(buf)
617 call datetime_set(sdate, vdate)
619 if (fld%geom%nx>9999)
call abor1_ftn(
"Format too small")
620 write(cnx,
'(I4)')fld%geom%nx
621 fmtn=
'('//trim(cnx)//fmt1//
')' 626 read(iunit,fmtn) (fld%gfld3d(jx,jy,jf), jx=1,fld%geom%nx)
630 allocate(zz(fld%geom%nx))
633 read(iunit,fmtn) (zz(jx), jx=1,fld%geom%nx)
640 read(iunit,fmt1) fld%xbound(jf)
643 read(iunit,fmtn) (fld%qbound(jx,jf), jx=1,fld%geom%nx)
652 call datetime_set(sdate, vdate)
710 use fckit_log_module,
only : fckit_log
715 type(
qg_field),
intent(inout) :: fld
716 type(
qg_geom),
intent(inout) :: geom
717 type(c_ptr),
intent(in) :: config
718 type(datetime),
intent(inout) :: vdate
720 character(len=30) :: ic
721 character(len=20) :: sdate
722 character(len=1024) :: buf
723 real(kind=kind_real) :: d1, d2, height(2), z, f1, f2, xdum(2)
724 real(kind=kind_real) :: deltax,deltay,deg_to_rad,rlat,rlon,xx,yy,kx,ky
725 real(kind=kind_real) :: latrange, lonrange, sclx, scly
726 real(kind=kind_real) :: p0,u0,v0,w0,t0,phis0,ps0,rho0,hum0,q1,q2,q3,q4
727 real(kind=kind_real),
allocatable :: rs(:,:)
728 integer :: ix, iy, il
730 if (config_element_exists(config,
"analytic_init"))
then 731 ic = trim(config_get_string(config,len(ic),
"analytic_init"))
734 ic =
"baroclinic-instability" 737 call fckit_log%warning(
"qg_fields:analytic_init: "//ic)
738 sdate = config_get_string(config,len(sdate),
"date")
739 write(buf,*)
'validity date is: '//sdate
740 call fckit_log%info(buf)
741 call datetime_set(sdate,vdate)
745 d1 = config_get_real(config,
"top_layer_depth")
746 d2 = config_get_real(config,
"bottom_layer_depth")
748 height(2) = 0.5_kind_real*d2
749 height(1) = d2 + 0.5_kind_real*d1
750 xdum(:) = 0.0_kind_real
758 allocate(rs(geom%nx,geom%ny))
761 deg_to_rad =
pi/180.0_kind_real
764 init_option:
select case (ic)
766 case (
"baroclinic-instability")
769 case (
"large-vortices")
771 latrange = geom%lat(geom%ny) - geom%lat(1)
772 lonrange = geom%lon(geom%nx) - geom%lon(1)
773 if (geom%lon(geom%nx) < geom%lon(1)) lonrange=lonrange+360.0_kind_real
777 sclx = (geom%nx-1.0_kind_real)/geom%nx
778 scly = (geom%ny-1.0_kind_real)/geom%ny
781 ky = 2.0_kind_real *
pi 785 do iy = 1,fld%geom%ny ;
do ix = 1, fld%geom%nx
787 xx = sclx*(geom%lon(ix)-geom%lon(1))/lonrange
788 if (geom%lon(ix) < geom%lon(1)) xx=xx+sclx*360.0_kind_real/lonrange
789 yy = scly*(geom%lat(iy)-geom%lat(1))/latrange
791 fld%x(ix,iy,il) = sin(kx*xx)*sin(ky*yy)
792 fld%u(ix,iy,il) = -ky*sin(kx*xx)*cos(ky*yy)
793 fld%v(ix,iy,il) = kx*cos(kx*xx)*sin(ky*yy)
799 call calc_pv(geom%nx,geom%ny,fld%q,fld%x,fld%x_north,fld%x_south,&
800 f1,f2,deltax,deltay,bet,rs,fld%lbc)
802 call calc_pv(geom%nx,geom%ny,fld%q,fld%x,xdum,xdum,&
803 f1,f2,deltax,deltay,bet,rs,fld%lbc)
806 case (
"dcmip-test-1-1")
810 do iy = 1,fld%geom%ny ;
do ix = 1, fld%geom%nx
813 rlat = deg_to_rad * geom%lat(iy)
814 rlon = deg_to_rad*modulo(geom%lon(ix)+180.0_kind_real,360.0_kind_real) -
pi 816 call test1_advection_deformation(rlon,rlat,p0,z,1,&
817 u0,v0,w0,t0,phis0,ps0,rho0,hum0,q1,q2,q3,q4)
819 fld%u(ix,iy,il) = u0 / ubar
820 fld%v(ix,iy,il) = v0 / ubar
829 call calc_pv(geom%nx,geom%ny,fld%q,fld%x,fld%x_north,fld%x_south,&
830 f1,f2,deltax,deltay,bet,rs,fld%lbc)
832 call calc_pv(geom%nx,geom%ny,fld%q,fld%x,xdum,xdum,&
833 f1,f2,deltax,deltay,bet,rs,fld%lbc)
836 case (
"dcmip-test-1-2")
840 do iy = 1,fld%geom%ny ;
do ix = 1, fld%geom%nx
843 rlat = deg_to_rad * geom%lat(iy)
844 rlon = deg_to_rad*modulo(geom%lon(ix)+180.0_kind_real,360.0_kind_real) -
pi 846 call test1_advection_hadley(rlon,rlat,p0,z,1,&
847 u0,v0,w0,t0,phis0,ps0,rho0,hum0,q1)
849 fld%u(ix,iy,il) = u0 / ubar
850 fld%v(ix,iy,il) = v0 / ubar
859 call calc_pv(geom%nx,geom%ny,fld%q,fld%x,fld%x_north,fld%x_south,&
860 f1,f2,deltax,deltay,bet,rs,fld%lbc)
862 call calc_pv(geom%nx,geom%ny,fld%q,fld%x,xdum,xdum,&
863 f1,f2,deltax,deltay,bet,rs,fld%lbc)
868 call abor1_ftn (
"qg_fields:analytic_init not properly defined")
870 end select init_option
896 integer,
intent(in) :: kx
897 integer,
intent(in) :: ky
898 real(kind=kind_real),
intent(out) :: x(kx,ky,2)
899 real(kind=kind_real),
intent(in) :: u(kx,ky,2)
900 real(kind=kind_real),
intent(in) :: v(kx,ky,2)
901 real(kind=kind_real),
intent(in) :: dx
902 real(kind=kind_real),
intent(in) :: dy
904 real(kind=kind_real),
allocatable :: vort(:,:), psi(:,:)
905 real(kind=kind_real),
allocatable :: dudy(:), dvdx(:)
906 integer :: ix, iy, il
908 allocate(vort(kx,ky),psi(kx,ky))
909 allocate(dudy(ky),dvdx(kx))
916 call deriv_1d(dvdx,v(:,iy,il),kx,dx,periodic=.true.)
921 call deriv_1d(dudy,u(ix,:,il),ky,dy)
922 vort(ix,:) = vort(ix,:) - dudy
931 deallocate(vort,psi,dudy,dvdx)
944 subroutine deriv_1d(df,f,n,delta,periodic)
946 real(kind=kind_real),
intent(In) :: f(:)
947 real(kind=kind_real),
intent(In) :: delta
948 Integer,
intent(In) :: n
949 real(kind=kind_real),
intent(InOut) :: df(:)
950 logical,
optional,
intent(In) :: periodic
953 real(kind=kind_real) :: ho2, ho12
956 if (
present(periodic))
then 962 ho2 = 1.0_kind_real/(2.0_kind_real*delta)
963 ho12 = 1.0_kind_real/(12.0_kind_real*delta)
967 df(i) = ho12*(f(i-2)-8.0_kind_real*f(i-1)+8.0_kind_real*f(i+1)-f(i+2))
972 df(1) = ho12*(f(n-1)-8.0_kind_real*f(n)+8.0_kind_real*f(2)-f(3))
973 df(2) = ho12*(f(n)-8.0_kind_real*f(1)+8.0_kind_real*f(3)-f(4))
974 df(n-1) = ho12*(f(n-3)-8.0_kind_real*f(n-2)+8.0_kind_real*f(n)-f(1))
975 df(n) = ho12*(f(n-2)-8.0_kind_real*f(n-1)+8.0_kind_real*f(1)-f(2))
980 df(1) = ho2*(-3.0_kind_real*f(1)+4.0_kind_real*f(2)-f(3))
981 df(2) = ho12*(-3.0_kind_real*f(1)-10.0_kind_real*f(2)+18.0_kind_real*f(3)-6.0_kind_real*f(4)+f(5))
984 df(n-1) = ho12*(3.0_kind_real*f(n)+10.0_kind_real*f(n-1)-18.0_kind_real*f(n-2)+6.0_kind_real*f(n-3)-f(n-4))
985 df(n) = ho2*(3.0_kind_real*f(n)-4.0_kind_real*f(n-1)+f(n-2))
996 use fckit_log_module,
only : fckit_log
1000 type(c_ptr),
intent(in) :: c_conf
1001 type(datetime),
intent(in) :: vdate
1003 integer,
parameter :: iunit=11
1004 integer,
parameter :: max_string_length=800
1005 integer :: ncid, nx_id, ny_id, nl_id, nc_id, ntot_id, four_id, gfld3d_id, xbound_id, qbound_id
1006 character(len=max_string_length+50) :: record
1007 character(len=max_string_length) :: filename
1008 character(len=20) :: sdate, fmtn
1009 character(len=4) :: cnx
1010 character(len=11) :: fmt1=
'(X,ES24.16)' 1011 character(len=1024):: buf
1012 integer :: jf, jy, jx, is
1016 filename =
genfilename(c_conf,max_string_length,vdate)
1017 WRITE(buf,*)
'qg_field:write_file: writing '//filename
1018 call fckit_log%info(buf)
1022 call datetime_to_string(vdate, sdate)
1026 call ncerr(nf90_create(trim(filename)//
'.nc',or(nf90_clobber,nf90_64bit_offset),ncid))
1027 call ncerr(nf90_def_dim(ncid,
'nx',fld%geom%nx,nx_id))
1028 call ncerr(nf90_def_dim(ncid,
'ny',fld%geom%ny,ny_id))
1029 call ncerr(nf90_def_dim(ncid,
'nl',fld%nl,nl_id))
1030 call ncerr(nf90_def_dim(ncid,
'nc',fld%nf,nc_id))
1031 call ncerr(nf90_def_dim(ncid,
'ntot',fld%nl*fld%nf,ntot_id))
1032 call ncerr(nf90_def_dim(ncid,
'four',4,four_id))
1033 call ncerr(nf90_put_att(ncid,nf90_global,
'lbc',is))
1035 call ncerr(nf90_put_att(ncid,nf90_global,
'sdate',sdate))
1036 call ncerr(nf90_def_var(ncid,
'gfld3d',nf90_double,(/nx_id,ny_id,ntot_id/),gfld3d_id))
1039 call ncerr(nf90_def_var(ncid,
'xbound',nf90_double,(/four_id/),xbound_id))
1040 call ncerr(nf90_def_var(ncid,
'qbound',nf90_double,(/nx_id,four_id/),qbound_id))
1043 call ncerr(nf90_enddef(ncid))
1045 call ncerr(nf90_put_var(ncid,gfld3d_id,fld%gfld3d))
1048 call ncerr(nf90_put_var(ncid,xbound_id,fld%xbound))
1049 call ncerr(nf90_put_var(ncid,qbound_id,fld%qbound))
1052 call ncerr(nf90_close(ncid))
1056 open(unit=iunit, file=trim(filename), form=
'formatted', action=
'write')
1058 write(iunit,*) fld%geom%nx, fld%geom%ny, fld%nl, fld%nf, is
1059 write(iunit,*) sdate
1061 if (fld%geom%nx>9999)
call abor1_ftn(
"Format too small")
1062 write(cnx,
'(I4)')fld%geom%nx
1063 fmtn=
'('//trim(cnx)//fmt1//
')' 1065 do jf=1,fld%nl*fld%nf
1067 write(iunit,fmtn) (fld%gfld3d(jx,jy,jf), jx=1,fld%geom%nx)
1073 write(iunit,fmt1) fld%xbound(jf)
1076 write(iunit,fmtn) (fld%qbound(jx,jf), jx=1,fld%geom%nx)
1088 subroutine gpnorm(fld, nf, pstat)
1091 integer,
intent(in) :: nf
1092 real(kind=kind_real),
intent(inout) :: pstat(3, nf)
1099 pstat(1,jj)=minval(fld%gfld3d(:,:,joff+1:joff+fld%nl))
1100 pstat(2,jj)=maxval(fld%gfld3d(:,:,joff+1:joff+fld%nl))
1101 pstat(3,jj)=sqrt(sum(fld%gfld3d(:,:,joff+1:joff+fld%nl)**2) &
1102 & /
real(fld%nl*fld%geom%nx*fld%geom%ny,
kind_real))
1108 pstat(1,jj)=minval(fld%xbound(:))
1109 pstat(2,jj)=maxval(fld%xbound(:))
1110 pstat(3,jj)=sqrt(sum(fld%xbound(:)**2)/
real(4,
kind_real))
1113 pstat(1,jj)=minval(fld%qbound(:,:))
1114 pstat(2,jj)=maxval(fld%qbound(:,:))
1115 pstat(3,jj)=sqrt(sum(fld%qbound(:,:)**2)/
real(4*fld%geom%nx,
kind_real))
1118 if (jj /= nf)
call abor1_ftn(
"qg_fields_gpnorm: error number of fields")
1125 subroutine fldrms(fld, prms)
1128 real(kind=kind_real),
intent(out) :: prms
1129 integer :: jf,jy,jx,ii
1130 real(kind=kind_real) :: zz
1140 zz = zz + fld%gfld3d(jx,jy,jf)*fld%gfld3d(jx,jy,jf)
1143 ii = ii + fld%geom%nx * fld%geom%ny
1148 zz = zz + fld%xbound(jf)*fld%xbound(jf)
1153 zz = zz + fld%qbound(jx,jf)*fld%qbound(jx,jf)
1156 ii = ii + 4*fld%geom%nx
1165 subroutine interp_tl(fld, locs, vars, gom)
1168 type(qg_locs),
intent(in) :: locs
1169 type(qg_vars),
intent(in) :: vars
1170 type(qg_goms),
intent(inout) :: gom
1171 real(kind=kind_real) :: di, dj, ai, aj, valb, valt
1172 integer :: jloc,joff,jvar,ii,jj,kk,iright,jsearch
1173 character(len=1) :: cvar
1179 di=locs%xyz(1,jloc)*
real(fld%geom%nx,kind_real) 1183 if (ii<1.or.ii>fld%geom%nx)
call abor1_ftn(
"qg_fields_interp_tl: error ii")
1185 if (iright==fld%geom%nx+1) iright=1
1187 dj=locs%xyz(2,jloc)*
real(fld%geom%ny,kind_real) 1191 if (jj<1.or.jj>fld%geom%ny)
call abor1_ftn(
"qg_fields_interp_tl: error jj")
1193 kk=nint(locs%xyz(3,jloc))
1197 if (vars%nv/=gom%nvar)
call abor1_ftn (
"qg_fields_interp_tl: inconsistent var and gom")
1199 cvar=vars%fldnames(jvar)
1202 if (fld%fldnames(jsearch)==cvar) joff=jsearch-1
1204 if (joff<0)
call abor1_ftn(
"qg_fields_interp_tl: unknown variable")
1209 valb=(1.0_kind_real-ai)*fld%gfld3d(ii ,jj,joff+kk) &
1210 & +ai *fld%gfld3d(iright,jj,joff+kk)
1216 valb=2.0_kind_real*( (1.0_kind_real-ai)*fld%gfld3d(ii,1,joff+kk) &
1217 & +ai *fld%gfld3d(iright,1,joff+kk) ) &
1218 & - ( (1.0_kind_real-ai)*fld%gfld3d(ii,2,joff+kk) &
1219 & +ai *fld%gfld3d(iright,2,joff+kk) )
1225 if (jj<fld%geom%ny)
then 1226 valt=(1.0_kind_real-ai)*fld%gfld3d(ii ,jj+1,joff+kk) &
1227 & +ai *fld%gfld3d(iright,jj+1,joff+kk)
1231 valt = 0.0_kind_real
1233 valt=2.0_kind_real*( (1.0_kind_real-ai)*fld%gfld3d(ii,fld%geom%ny,joff+kk) &
1234 & +ai *fld%gfld3d(iright,fld%geom%ny,joff+kk) ) &
1235 & - ( (1.0_kind_real-ai)*fld%gfld3d(ii,fld%geom%ny-1,joff+kk) &
1236 & +ai *fld%gfld3d(iright,fld%geom%ny-1,joff+kk) )
1238 valt = 0.0_kind_real
1243 gom%values(jvar,gom%used) = (1.0_kind_real-aj)*valb + aj*valt
1252 subroutine interp_ad(fld, locs, vars, gom)
1254 type(
qg_field),
intent(inout) :: fld
1255 type(qg_locs),
intent(in) :: locs
1256 type(qg_vars),
intent(in) :: vars
1257 type(qg_goms),
intent(inout) :: gom
1258 real(kind=kind_real) :: di, dj, ai, aj, valb, valt
1259 integer :: jloc,joff,jvar,ii,jj,kk,iright,jsearch
1260 character(len=1) :: cvar
1264 do jloc=locs%nloc,1,-1
1266 di=locs%xyz(1,jloc)*
real(fld%geom%nx,
kind_real)
1270 if (ii<1.or.ii>fld%geom%nx)
call abor1_ftn(
"qg_fields_interp_ad: error ii")
1272 if (iright==fld%geom%nx+1) iright=1
1274 dj=locs%xyz(2,jloc)*
real(fld%geom%ny,
kind_real)
1278 if (jj<1.or.jj>fld%geom%ny)
call abor1_ftn(
"qg_fields_interp_ad: error jj")
1280 kk=nint(locs%xyz(3,jloc))
1284 if (vars%nv/=gom%nvar)
call abor1_ftn (
"qg_fields_interp_tl: inconsistent var and gom")
1285 do jvar=vars%nv,1,-1
1286 cvar=vars%fldnames(jvar)
1289 if (fld%fldnames(jsearch)==cvar) joff=jsearch-1
1291 if (joff<0)
call abor1_ftn(
"qg_fields_interp_ad: unknown variable")
1295 valb = (1.0_kind_real-aj)*gom%values(jvar,gom%nobs-gom%used+1)
1296 valt = aj*gom%values(jvar,gom%nobs-gom%used+1)
1300 fld%gfld3d(ii ,jj,joff+kk) = &
1301 & fld%gfld3d(ii ,jj,joff+kk)+(1.0_kind_real-ai)*valb
1302 fld%gfld3d(iright,jj,joff+kk) = &
1303 & fld%gfld3d(iright,jj,joff+kk)+ai*valb
1307 fld%gfld3d(ii,1,joff+kk) = &
1308 & fld%gfld3d(ii,1,joff+kk)+2.0_kind_real*(1.0_kind_real-ai)*valb
1309 fld%gfld3d(iright,1,joff+kk) = &
1310 & fld%gfld3d(iright,1,joff+kk)+2.0_kind_real*ai*valb
1311 fld%gfld3d(ii,2,joff+kk) = &
1312 & fld%gfld3d(ii,2,joff+kk)-(1.0_kind_real-ai)*valb
1313 fld%gfld3d(iright,2,joff+kk) = &
1314 & fld%gfld3d(iright,2,joff+kk)-ai*valb
1318 if (jj<fld%geom%ny)
then 1319 fld%gfld3d(ii ,jj+1,joff+kk) = &
1320 & fld%gfld3d(ii ,jj+1,joff+kk)+(1.0_kind_real-ai)*valt
1321 fld%gfld3d(iright,jj+1,joff+kk) = &
1322 & fld%gfld3d(iright,jj+1,joff+kk)+ai*valt
1326 fld%gfld3d(ii,fld%geom%ny,joff+kk) = &
1327 & fld%gfld3d(ii,fld%geom%ny,joff+kk)+2.0_kind_real*(1.0_kind_real-ai)*valt
1328 fld%gfld3d(iright,fld%geom%ny,joff+kk) = &
1329 & fld%gfld3d(iright,fld%geom%ny,joff+kk)+2.0_kind_real*ai*valt
1330 fld%gfld3d(ii,fld%geom%ny-1,joff+kk) = &
1331 & fld%gfld3d(ii,fld%geom%ny-1,joff+kk)-(1.0_kind_real-ai)*valt
1332 fld%gfld3d(iright,fld%geom%ny-1,joff+kk)= &
1333 & fld%gfld3d(iright,fld%geom%ny-1,joff+kk)-ai*valt
1344 subroutine lin_weights(kk,delta1,delta2,k1,k2,w1,w2)
1346 integer,
intent(in) :: kk
1347 real(kind=kind_real),
intent(in) :: delta1,delta2
1348 integer,
intent(out) :: k1,k2
1349 real(kind=kind_real),
intent(out) :: w1,w2
1352 real(kind=kind_real) :: zz
1354 zz=
real(kk-1,kind_real)*delta1
1357 w1=zz-
real(ii,kind_real)
1370 type(qg_field),
intent(in) :: self
1371 type(unstructured_grid),
intent(inout) :: ug
1375 if (ug%colocated==1)
then 1384 if (.not.
allocated(ug%grid))
allocate(ug%grid(ug%ngrid))
1386 if (ug%colocated==1)
then 1390 ug%grid(1)%nmga = self%geom%nx*self%geom%ny
1393 ug%grid(1)%nl0 = self%nl
1396 ug%grid(1)%nv = self%nf
1404 ug%grid(igrid)%nmga = self%geom%nx*self%geom%ny
1407 ug%grid(igrid)%nl0 = self%nl
1410 ug%grid(igrid)%nv = self%nf
1413 ug%grid(igrid)%nts = 1
1421 subroutine ug_coord(self, ug, colocated)
1426 integer,
intent(in) :: colocated
1428 integer :: igrid,imga,jx,jy,jl
1431 ug%colocated = colocated
1440 if (ug%colocated==1)
then 1443 do jy=1,self%geom%ny
1444 do jx=1,self%geom%nx
1446 ug%grid(1)%lon(imga) = self%geom%lon(jx)
1447 ug%grid(1)%lat(imga) = self%geom%lat(jy)
1448 ug%grid(1)%area(imga) = self%geom%area(jx,jy)
1450 ug%grid(1)%vunit(imga,jl) =
real(jl,kind=
kind_real)
1451 ug%grid(1)%lmask(imga,jl) = .true.
1459 do jy=1,self%geom%ny
1460 do jx=1,self%geom%nx
1462 ug%grid(igrid)%lon(imga) = self%geom%lon(jx)
1463 ug%grid(igrid)%lat(imga) = self%geom%lat(jy)
1464 ug%grid(igrid)%area(imga) = self%geom%area(jx,jy)
1466 ug%grid(igrid)%vunit(imga,jl) =
real(jl,kind=
kind_real)
1467 ug%grid(igrid)%lmask(imga,jl) = .true.
1483 integer,
intent(in) :: colocated
1485 integer :: igrid,imga,jx,jy,jl,jf,joff
1488 ug%colocated = colocated
1497 if (ug%colocated==1)
then 1500 do jy=1,self%geom%ny
1501 do jx=1,self%geom%nx
1504 joff = (jf-1)*self%nl
1506 ug%grid(1)%fld(imga,jl,jf,1) = self%gfld3d(jx,jy,joff+jl)
1515 do jy=1,self%geom%ny
1516 do jx=1,self%geom%nx
1519 joff = (jf-1)*self%nl
1521 ug%grid(igrid)%fld(imga,jl,jf,1) = self%gfld3d(jx,jy,joff+jl)
1536 type(
qg_field),
intent(inout) :: self
1539 integer :: igrid,imga,jx,jy,jl,jf,joff
1542 if (ug%colocated==1)
then 1545 do jy=1,self%geom%ny
1546 do jx=1,self%geom%nx
1549 joff = (jf-1)*self%nl
1551 self%gfld3d(jx,jy,joff+jl) = ug%grid(1)%fld(imga,jl,jf,1)
1560 do jy=1,self%geom%ny
1561 do jx=1,self%geom%nx
1564 joff = (jf-1)*self%nl
1566 self%gfld3d(jx,jy,joff+jl) = ug%grid(igrid)%fld(imga,jl,jf,1)
1582 type(c_ptr),
intent(in) :: c_conf
1583 integer,
intent(in) :: length
1585 type(datetime),
intent(in) :: vdate
1587 character(len=length) :: fdbdir, expver, typ, validitydate, referencedate, sstep, &
1589 type(datetime) :: rdate
1590 type(duration) :: step
1596 fdbdir = config_get_string(c_conf,len(fdbdir),
"datadir")
1597 expver = config_get_string(c_conf,len(expver),
"exp")
1598 typ = config_get_string(c_conf,len(typ) ,
"type")
1600 if (typ==
"ens")
then 1601 mmb = config_get_string(c_conf, len(mmb),
"member")
1602 lenfn = len_trim(fdbdir) + 1 + len_trim(expver) + 1 + len_trim(typ) + 1 + len_trim(mmb)
1603 prefix = trim(fdbdir) //
"/" // trim(expver) //
"." // trim(typ) //
"." // trim(mmb)
1605 lenfn = len_trim(fdbdir) + 1 + len_trim(expver) + 1 + len_trim(typ)
1606 prefix = trim(fdbdir) //
"/" // trim(expver) //
"." // trim(typ)
1609 if (typ==
"fc" .or. typ==
"ens")
then 1610 referencedate = config_get_string(c_conf,len(referencedate),
"date")
1611 call datetime_to_string(vdate, validitydate)
1612 call datetime_create(trim(referencedate), rdate)
1613 call datetime_diff(vdate, rdate, step)
1614 call duration_to_string(step, sstep)
1615 lenfn = lenfn + 1 + len_trim(referencedate) + 1 + len_trim(sstep)
1616 genfilename = trim(prefix) //
"." // trim(referencedate) //
"." // trim(sstep)
1620 call datetime_to_string(vdate, validitydate)
1621 lenfn = lenfn + 1 + len_trim(validitydate)
1622 genfilename = trim(prefix) //
"." // trim(validitydate)
1626 &
call abor1_ftn(
"qg_fields:genfilename: filename too long")
1635 type(
qg_field),
intent(in) :: x1, x2
1645 if (x1%fldnames(jf)/=x2%fldnames(jf)) &
1646 &
call abor1_ftn(
"common_vars: fields do not match")
1648 if (x1%nl /= x2%nl)
call abor1_ftn(
"common_vars: error number of levels")
1658 type(qg_field),
intent(in) :: x1, x2
1660 if (x1%geom%nx /= x2%geom%nx .or. x1%geom%ny /= x2%geom%ny .or. x1%nl /= x2%nl)
then 1661 call abor1_ftn (
"qg_fields: resolution error")
1670 subroutine check(self)
1672 type(qg_field),
intent(in) :: self
1675 bad = .not.
associated(self%gfld3d)
1677 bad = bad .or. (
size(self%gfld3d, 1) /= self%geom%nx)
1678 bad = bad .or. (
size(self%gfld3d, 2) /= self%geom%ny)
1679 bad = bad .or. (
size(self%gfld3d, 3) /= self%nl*self%nf)
1681 bad = bad .or. .not.
associated(self%x)
1684 bad = bad .or. .not.
associated(self%q)
1685 bad = bad .or. .not.
associated(self%u)
1686 bad = bad .or. .not.
associated(self%v)
1688 bad = bad .or.
associated(self%q)
1689 bad = bad .or.
associated(self%u)
1690 bad = bad .or.
associated(self%v)
1696 bad = bad .or. .not.
associated(self%xbound)
1697 bad = bad .or. (
size(self%xbound) /= 4)
1699 bad = bad .or. .not.
associated(self%qbound)
1700 bad = bad .or. (
size(self%qbound, 1) /= self%geom%nx)
1701 bad = bad .or. (
size(self%qbound, 2) /= 4)
1703 bad = bad .or.
associated(self%xbound)
1704 bad = bad .or.
associated(self%qbound)
1708 write(0,*)
'nx, ny, nf, nl, lbc = ',self%geom%nx,self%geom%ny,self%nf,self%nl,self%lbc
1709 if (
associated(self%gfld3d))
write(0,*)
'shape(gfld3d) = ',shape(self%gfld3d)
1710 if (
associated(self%xbound))
write(0,*)
'shape(xbound) = ',shape(self%xbound)
1711 if (
associated(self%qbound))
write(0,*)
'shape(qbound) = ',shape(self%qbound)
1712 call abor1_ftn (
"qg_fields: field not consistent")
1715 end subroutine check 1719 subroutine ncerr(info)
1724 integer,
intent(in) :: info
1727 if (info/=nf90_noerr)
then 1728 write(*,*) trim(nf90_strerror(info))
1732 end subroutine ncerr real(kind=kind_real), parameter domain_meridional
meridional model domain (m)
Fortran derived type to represent QG model variables.
subroutine, public allocate_unstructured_grid_coord(self)
Fortran generic for generating random 1d, 2d and 3d arrays.
subroutine, public self_mul(self, zz)
subroutine calc_streamfunction(kx, ky, x, u, v, dx, dy)
Calculate Streamfunction from u and v.
subroutine, public axpy(self, zz, rhs)
type(registry_t), public qg_field_registry
Linked list interface - defines registry_t type.
subroutine, public read_file(fld, c_conf, vdate)
real(kind=kind_real), parameter f0
Coriolis parameter at southern boundary.
character(len=length) function genfilename(c_conf, length, vdate)
Fortran derived type to hold geometry data for the QG model.
subroutine lin_weights(kk, delta1, delta2, k1, k2, w1, w2)
subroutine check(action, status)
real(kind=kind_real), parameter g
gravity (m^2 s^{-2})
subroutine test1_advection_deformation(lon, lat, p, z, zcoords, u, v, w, t, phis, ps, rho, q, q1, q2, q3, q4)
subroutine, public copy(self, rhs)
subroutine, public create(self, geom, vars)
Linked list implementation.
subroutine deriv_1d(df, f, n, delta, periodic)
Finite Difference Derivative.
subroutine, public random(self)
subroutine, public self_schur(self, rhs)
subroutine, public self_add(self, rhs)
Constants for the QG model.
subroutine, public add_incr(self, rhs)
subroutine ug_size(self, ug)
subroutine, public interp_tl(fld, locs, vars, gom)
subroutine solve_helmholz(x, b, c, nx, ny, deltax, deltay)
Solve a Helmholz equation.
subroutine check_resolution(x1, x2)
subroutine calc_pv(kx, ky, pv, x, x_north, x_south, f1, f2, deltax, deltay, bet, rs, lbc)
Calculate potential vorticity from streamfunction.
Fortran module handling geometry for the QG model.
subroutine, public diff_incr(lhs, x1, x2)
subroutine, public dirac(self, c_conf)
subroutine, public ug_coord(self, ug, colocated)
subroutine, public field_to_ug(self, ug, colocated)
Fortran module handling observation locations.
subroutine invent_state(flds, config)
Invent an initial state for the QG model.
subroutine, public write_file(fld, c_conf, vdate)
subroutine, public field_from_ug(self, ug)
subroutine, public interp_ad(fld, locs, vars, gom)
subroutine, public allocate_unstructured_grid_field(self)
subroutine, public dot_prod(fld1, fld2, zprod)
Fortran derived type to hold QG fields.
Fortran module to handle variables for the QG model.
Handle fields for the QG model.
Fortran module for generating random vectors.
subroutine test1_advection_hadley(lon, lat, p, z, zcoords, u, v, w, t, phis, ps, rho, q, q1)
subroutine, public analytic_init(fld, geom, config, vdate)
Analytic Initialization for the QG model.
subroutine, public zeros(self)
subroutine, public fldrms(fld, prms)
subroutine, public self_sub(self, rhs)
real(kind=kind_real), parameter domain_zonal
model domain (m) in zonal direction
real(kind=kind_real), parameter dlogtheta
difference in log(pot. T) across boundary
integer function common_vars(x1, x2)
subroutine, public change_resol(fld, rhs)
Fortran module handling interpolated (to obs locations) model variables.
integer, parameter, public kind_real
Fortran module for handling generic unstructured grid.
subroutine, public gpnorm(fld, nf, pstat)
real(kind=kind_real), parameter scale_length
horizontal length scale (m)
real(fp), parameter, public pi
subroutine, public delete(self)