11 use atlas_module,
only: atlas_field, atlas_fieldset, atlas_real, atlas_functionspace_pointcloud
12 use fckit_configuration_module,
only: fckit_configuration
13 use fckit_log_module,
only: fckit_log
30 real(kind_real) :: deltax
31 real(kind_real) :: deltay
32 real(kind_real),
allocatable :: x(:)
33 real(kind_real),
allocatable :: y(:)
34 real(kind_real),
allocatable :: z(:)
35 real(kind_real),
allocatable :: lat(:,:)
36 real(kind_real),
allocatable :: lon(:,:)
37 real(kind_real),
allocatable :: area(:,:)
38 real(kind_real),
allocatable :: f(:,:)
39 real(kind_real),
allocatable :: f_p(:,:)
40 real(kind_real),
allocatable :: f_pinv(:,:)
41 real(kind_real),
allocatable :: f_d(:)
42 real(kind_real),
allocatable :: bet(:)
43 real(kind_real),
allocatable :: heat(:,:)
44 type(atlas_functionspace_pointcloud) :: afunctionspace
47 #define LISTED_TYPE qg_geom
50 #include "oops/util/linkedList_i.f"
60 #include "oops/util/linkedList_c.f"
66 type(
qg_geom),
intent(inout) :: self
67 type(fckit_configuration),
intent(in) :: f_conf
70 integer :: ix,iy,iz,ix_c,iy_c,lwork,info
71 integer,
allocatable :: ipiv(:),ipivsave(:)
72 real(kind_real) :: mapfac,distx,disty,f
73 real(kind_real),
allocatable :: real_array(:),depths(:),wi(:),vl(:,:),work(:)
74 real(kind_real),
allocatable :: fsave(:,:),vrlu(:,:),vrlusave(:,:)
75 character(len=1024) :: record
77 character(len=:),
allocatable :: str
80 call f_conf%get_or_die(
"nx",self%nx)
81 call f_conf%get_or_die(
"ny",self%ny)
82 self%nz = f_conf%get_size(
"depths")
85 allocate(depths(self%nz))
86 allocate(self%x(self%nx))
87 allocate(self%y(self%ny))
88 allocate(self%z(self%nz))
89 allocate(self%lon(self%nx,self%ny))
90 allocate(self%lat(self%nx,self%ny))
91 allocate(self%area(self%nx,self%ny))
92 allocate(self%f(self%nz,self%nz))
93 allocate(self%f_p(self%nz,self%nz))
94 allocate(self%f_pinv(self%nz,self%nz))
95 allocate(self%f_d(self%nz))
96 allocate(self%bet(self%ny))
97 allocate(self%heat(self%nx,self%ny))
99 allocate(vl(self%nz,self%nz))
100 allocate(fsave(self%nz,self%nz))
101 allocate(vrlu(self%nz,self%nz))
102 allocate(vrlusave(self%nz,self%nz))
103 allocate(ipiv(self%nz))
104 allocate(ipivsave(self%nz))
107 call f_conf%get_or_die(
"depths",real_array)
115 write(record,
'(a,i3,a,i3,a,i3)')
'qg_geom_create: nx/ny/nz = ',self%nx,
' /',self%ny,
' /',self%nz
116 call fckit_log%info(record)
117 write(record,
'(a,f7.2,a,f7.2,a)')
' deltax/deltay = ',self%deltax*1.0e-3,
' km / ',self%deltay*1.0e-3,
' km'
118 call fckit_log%info(record)
122 self%x(ix) = (real(ix,kind_real)-0.5)*self%deltax
125 self%y(iy) = real(iy,kind_real)*self%deltay
131 call xy_to_lonlat(self%x(ix),self%y(iy),self%lon(ix,iy),self%lat(ix,iy),mapfac)
132 self%area(ix,iy) = self%deltax*self%deltay/mapfac
137 self%z(1) = 0.5*depths(1)
139 self%z(iz) = sum(depths(1:iz-1))+0.5*depths(iz)
148 self%f(iz,iz) = self%f(iz,iz)-f
152 self%f(iz,iz) = self%f(iz,iz)-f
159 call dgeev(
'V',
'V',self%nz,fsave,self%nz,self%f_d,wi,vl,self%nz,self%f_p,self%nz,work,-1,info)
160 if (info/=0)
call abor1_ftn(
'error in dgeev, first pass')
163 allocate(work(lwork))
165 call dgeev(
'V',
'V',self%nz,fsave,self%nz,self%f_d,wi,vl,self%nz,self%f_p,self%nz,work,lwork,info)
166 if (info/=0)
call abor1_ftn(
'error in dgeev, second pass')
171 call dgetrf(self%nz,self%nz,vrlu,self%nz,ipiv,info)
172 if (info/=0)
call abor1_ftn(
'error in dgetrf')
176 call dgetri(self%nz,vrlusave,self%nz,ipivsave,work,-1,info)
177 if (info/=0)
call abor1_ftn(
'error in dgetri, first pass')
180 allocate(work(lwork))
183 call dgetri(self%nz,self%f_pinv,self%nz,ipivsave,work,lwork,info)
184 if (info/=0)
call abor1_ftn(
'error in dgetri, second pass')
189 self%bet(iy) = real(iy-(self%ny+1)/2,kind_real)*self%deltay*
bet0
193 call f_conf%get_or_die(
"heating",htype)
194 if (.not. htype)
then
196 call fckit_log%info(
'qg_geom_setup: heating off')
199 call fckit_log%info(
'qg_geom_setup: Gaussian heating on')
205 distx = abs(self%x(ix)-self%x(ix_c))
207 disty = abs(self%y(iy)-self%y(iy_c))
219 type(
qg_geom),
intent(inout) :: self
220 type(atlas_fieldset),
intent(inout) :: afieldset
223 integer :: ix,iy,inode
224 real(kind_real),
pointer :: real_ptr(:,:)
225 type(atlas_field) :: afield
228 afield = atlas_field(name=
"lonlat", kind=atlas_real(kind_real), shape=(/2,self%nx*self%ny/))
229 call afield%data(real_ptr)
234 real_ptr(1,inode) = self%lon(ix,iy)
235 real_ptr(2,inode) = self%lat(ix,iy)
238 call afieldset%add(afield)
247 type(
qg_geom),
intent(inout) :: self
248 type(atlas_fieldset),
intent(inout) :: afieldset
251 integer :: ix,iy,iz,inode
252 real(kind_real),
pointer :: real_ptr_1(:),real_ptr_2(:,:)
253 type(atlas_field) :: afield
256 afield = self%afunctionspace%create_field(name=
'area',kind=atlas_real(kind_real),levels=0)
257 call afield%data(real_ptr_1)
262 real_ptr_1(inode) = self%area(ix,iy)
265 call afieldset%add(afield)
269 afield = self%afunctionspace%create_field(name=
'vunit',kind=atlas_real(kind_real),levels=self%nz)
270 call afield%data(real_ptr_2)
272 real_ptr_2(iz,1:self%nx*self%ny) = self%z(iz)
274 call afieldset%add(afield)
283 type(
qg_geom),
intent(inout) :: self
284 type(
qg_geom),
intent(in) :: other
292 allocate(self%x(self%nx))
293 allocate(self%y(self%ny))
294 allocate(self%z(self%nz))
295 allocate(self%lon(self%nx,self%ny))
296 allocate(self%lat(self%nx,self%ny))
297 allocate(self%area(self%nx,self%ny))
298 allocate(self%f(self%nz,self%nz))
299 allocate(self%f_p(self%nz,self%nz))
300 allocate(self%f_pinv(self%nz,self%nz))
301 allocate(self%f_d(self%nz))
302 allocate(self%bet(self%ny))
303 allocate(self%heat(self%nx,self%ny))
306 self%deltax = other%deltax
307 self%deltay = other%deltay
313 self%area = other%area
316 self%f_pinv = other%f_pinv
319 self%heat = other%heat
320 self%afunctionspace = atlas_functionspace_pointcloud(other%afunctionspace%c_ptr())
328 type(
qg_geom),
intent(inout) :: self
336 deallocate(self%area)
339 deallocate(self%f_pinv)
342 deallocate(self%heat)
343 call self%afunctionspace%final()
351 type(
qg_geom),
intent(in) :: self
352 integer,
intent(out) :: nx
353 integer,
intent(out) :: ny
354 integer,
intent(out) :: nz
355 real(kind_real),
intent(out) :: deltax
356 real(kind_real),
intent(out) :: deltay