10 use fckit_mpi_module,
only: fckit_mpi_sum
37 integer,
allocatable :: h_n_s(:,:)
38 integer,
allocatable :: h_c2b(:,:,:)
39 real(kind_real),
allocatable :: h_s(:,:,:)
57 real(kind_real),
parameter ::
var_th = 0.8
73 class(vbal_type),
intent(inout) :: vbal
74 type(mpl_type),
intent(in) :: mpl
75 type(nam_type),
intent(in) :: nam
76 type(geom_type),
intent(in) :: geom
77 type(bpar_type),
intent(in) :: bpar
84 if (trim(nam%diag_interp)==
'bilin')
then 87 elseif (trim(nam%diag_interp)==
'natural')
then 91 call mpl%abort(
'wrong interpolation type')
95 allocate(vbal%h_n_s(geom%nc0a,geom%nl0i))
96 allocate(vbal%h_c2b(vbal%np,geom%nc0a,geom%nl0i))
97 allocate(vbal%h_S(vbal%np,geom%nc0a,geom%nl0i))
98 allocate(vbal%blk(nam%nv,nam%nv))
101 if (bpar%vbal_block(iv,jv))
then 102 call vbal%blk(iv,jv)%alloc(nam,geom,vbal%samp%nc2b,iv,jv)
108 vbal%allocated = .true.
121 class(vbal_type),
intent(inout) :: vbal
122 type(nam_type),
intent(in) :: nam
128 if (
allocated(vbal%h_n_s))
deallocate(vbal%h_n_s)
129 if (
allocated(vbal%h_c2b))
deallocate(vbal%h_c2b)
130 if (
allocated(vbal%h_S))
deallocate(vbal%h_S)
131 if (
allocated(vbal%blk))
then 134 call vbal%blk(iv,jv)%dealloc
141 vbal%allocated = .false.
149 subroutine vbal_read(vbal,mpl,nam,geom,bpar)
154 class(vbal_type),
intent(inout) :: vbal
155 type(mpl_type),
intent(in) :: mpl
156 type(nam_type),
intent(in) :: nam
157 type(geom_type),
intent(in) :: geom
158 type(bpar_type),
intent(in) :: bpar
162 integer :: ncid,np_id,nc0a_id,nc2b_id,nl0i_id,nl0_1_id,nl0_2_id,h_n_s_id,h_c2b_id,h_S_id,reg_id(nam%nv,nam%nv)
163 integer :: nc0a_test,nl0i_test,nl0_1_test,nl0_2_test
164 character(len=1024) :: filename
165 character(len=1024),
parameter :: subr=
'vbal_read' 168 write(filename,
'(a,a,i4.4,a,i4.4,a)') trim(nam%prefix),
'_vbal_',mpl%nproc,
'-',mpl%myproc,
'.nc' 169 call mpl%ncerr(subr,nf90_open(trim(nam%datadir)//
'/'//trim(filename),or(nf90_clobber,nf90_64bit_offset),ncid))
172 call mpl%ncerr(subr,nf90_inq_dimid(ncid,
'np',np_id))
173 call mpl%ncerr(subr,nf90_inquire_dimension(ncid,np_id,len=vbal%np))
174 call mpl%ncerr(subr,nf90_inq_dimid(ncid,
'nc0a',nc0a_id))
175 call mpl%ncerr(subr,nf90_inquire_dimension(ncid,nc0a_id,len=nc0a_test))
176 if (nc0a_test/=geom%nc0a)
call mpl%abort(
'wrong dimension when reading vbal')
177 call mpl%ncerr(subr,nf90_inq_dimid(ncid,
'nc2b',nc2b_id))
178 call mpl%ncerr(subr,nf90_inquire_dimension(ncid,nc2b_id,len=vbal%samp%nc2b))
179 call mpl%ncerr(subr,nf90_inq_dimid(ncid,
'nl0i',nl0i_id))
180 call mpl%ncerr(subr,nf90_inquire_dimension(ncid,nl0i_id,len=nl0i_test))
181 if (nl0i_test/=geom%nl0i)
call mpl%abort(
'wrong dimension when reading vbal')
182 call mpl%ncerr(subr,nf90_inq_dimid(ncid,
'nl0_1',nl0_1_id))
183 call mpl%ncerr(subr,nf90_inquire_dimension(ncid,nl0_1_id,len=nl0_1_test))
184 if (nl0_1_test/=geom%nl0)
call mpl%abort(
'wrong dimension when reading vbal')
185 call mpl%ncerr(subr,nf90_inq_dimid(ncid,
'nl0_2',nl0_2_id))
186 call mpl%ncerr(subr,nf90_inquire_dimension(ncid,nl0_2_id,len=nl0_2_test))
187 if (nl0_2_test/=geom%nl0)
call mpl%abort(
'wrong dimension when reading vbal')
190 allocate(vbal%h_n_s(geom%nc0a,geom%nl0i))
191 allocate(vbal%h_c2b(vbal%np,geom%nc0a,geom%nl0i))
192 allocate(vbal%h_S(vbal%np,geom%nc0a,geom%nl0i))
193 allocate(vbal%blk(nam%nv,nam%nv))
196 if (bpar%vbal_block(iv,jv))
then 197 call vbal%blk(iv,jv)%alloc(nam,geom,vbal%samp%nc2b,iv,jv)
203 call mpl%ncerr(subr,nf90_inq_varid(ncid,
'h_n_s',h_n_s_id))
204 call mpl%ncerr(subr,nf90_inq_varid(ncid,
'h_c2b',h_c2b_id))
205 call mpl%ncerr(subr,nf90_inq_varid(ncid,
'h_S',h_s_id))
208 if (bpar%vbal_block(iv,jv))
call mpl%ncerr(subr,nf90_inq_varid(ncid,trim(vbal%blk(iv,jv)%name)//
'_reg',reg_id(iv,jv)))
213 call mpl%ncerr(subr,nf90_get_var(ncid,h_n_s_id,vbal%h_n_s))
214 call mpl%ncerr(subr,nf90_get_var(ncid,h_c2b_id,vbal%h_c2b))
215 call mpl%ncerr(subr,nf90_get_var(ncid,h_s_id,vbal%h_S))
218 if (bpar%vbal_block(iv,jv))
call mpl%ncerr(subr,nf90_get_var(ncid,reg_id(iv,jv),vbal%blk(iv,jv)%reg))
223 call mpl%ncerr(subr,nf90_close(ncid))
236 class(vbal_type),
intent(inout) :: vbal
237 type(mpl_type),
intent(in) :: mpl
238 type(nam_type),
intent(in) :: nam
239 type(geom_type),
intent(in) :: geom
240 type(bpar_type),
intent(in) :: bpar
244 integer :: ncid,np_id,nc0a_id,nc2b_id,nl0i_id,nl0_1_id,nl0_2_id,h_n_s_id,h_c2b_id,h_S_id
245 integer :: reg_id(nam%nv,nam%nv),auto_id(nam%nv,nam%nv),cross_id(nam%nv,nam%nv),auto_inv_id(nam%nv,nam%nv)
246 character(len=1024) :: filename
247 character(len=1024),
parameter :: subr=
'vbal_write' 250 write(filename,
'(a,a,i4.4,a,i4.4,a)') trim(nam%prefix),
'_vbal_',mpl%nproc,
'-',mpl%myproc,
'.nc' 251 call mpl%ncerr(subr,nf90_create(trim(nam%datadir)//
'/'//trim(filename),or(nf90_clobber,nf90_64bit_offset),ncid))
254 call nam%ncwrite(mpl,ncid)
257 call mpl%ncerr(subr,nf90_def_dim(ncid,
'np',vbal%np,np_id))
258 call mpl%ncerr(subr,nf90_def_dim(ncid,
'nc0a',geom%nc0a,nc0a_id))
259 call mpl%ncerr(subr,nf90_def_dim(ncid,
'nc2b',vbal%samp%nc2b,nc2b_id))
260 call mpl%ncerr(subr,nf90_def_dim(ncid,
'nl0i',geom%nl0i,nl0i_id))
261 call mpl%ncerr(subr,nf90_def_dim(ncid,
'nl0_1',geom%nl0,nl0_1_id))
262 call mpl%ncerr(subr,nf90_def_dim(ncid,
'nl0_2',geom%nl0,nl0_2_id))
265 call mpl%ncerr(subr,nf90_def_var(ncid,
'h_n_s',nf90_int,(/nc0a_id,nl0i_id/),h_n_s_id))
266 call mpl%ncerr(subr,nf90_put_att(ncid,h_n_s_id,
'_FillValue',
msvali))
267 call mpl%ncerr(subr,nf90_def_var(ncid,
'h_c2b',nf90_int,(/np_id,nc0a_id,nl0i_id/),h_c2b_id))
268 call mpl%ncerr(subr,nf90_put_att(ncid,h_c2b_id,
'_FillValue',
msvali))
269 call mpl%ncerr(subr,nf90_def_var(ncid,
'h_S',
ncfloat,(/np_id,nc0a_id,nl0i_id/),h_s_id))
270 call mpl%ncerr(subr,nf90_put_att(ncid,h_s_id,
'_FillValue',
msvalr))
273 if (bpar%vbal_block(iv,jv))
then 274 call mpl%ncerr(subr,nf90_def_var(ncid,trim(vbal%blk(iv,jv)%name)//
'_auto',
ncfloat,(/nc2b_id,nl0_1_id,nl0_2_id/), &
276 call mpl%ncerr(subr,nf90_def_var(ncid,trim(vbal%blk(iv,jv)%name)//
'_cross',
ncfloat,(/nc2b_id,nl0_1_id,nl0_2_id/), &
278 call mpl%ncerr(subr,nf90_def_var(ncid,trim(vbal%blk(iv,jv)%name)//
'_auto_inv',
ncfloat,(/nc2b_id,nl0_1_id,nl0_2_id/), &
279 & auto_inv_id(iv,jv)))
280 call mpl%ncerr(subr,nf90_def_var(ncid,trim(vbal%blk(iv,jv)%name)//
'_reg',
ncfloat,(/nc2b_id,nl0_1_id,nl0_2_id/), &
287 call mpl%ncerr(subr,nf90_enddef(ncid))
290 call mpl%ncerr(subr,nf90_put_var(ncid,h_n_s_id,vbal%h_n_s))
291 call mpl%ncerr(subr,nf90_put_var(ncid,h_c2b_id,vbal%h_c2b))
292 call mpl%ncerr(subr,nf90_put_var(ncid,h_s_id,vbal%h_S))
295 if (bpar%vbal_block(iv,jv))
then 296 call mpl%ncerr(subr,nf90_put_var(ncid,reg_id(iv,jv),vbal%blk(iv,jv)%reg))
297 call mpl%ncerr(subr,nf90_put_var(ncid,auto_id(iv,jv),vbal%blk(iv,jv)%auto))
298 call mpl%ncerr(subr,nf90_put_var(ncid,cross_id(iv,jv),vbal%blk(iv,jv)%cross))
299 call mpl%ncerr(subr,nf90_put_var(ncid,auto_inv_id(iv,jv),vbal%blk(iv,jv)%auto_inv))
305 call mpl%ncerr(subr,nf90_close(ncid))
313 subroutine vbal_run_vbal(vbal,mpl,rng,nam,geom,bpar,io,ens,ensu)
318 class(vbal_type),
intent(inout) :: vbal
319 type(mpl_type),
intent(inout) :: mpl
320 type(rng_type),
intent(inout) :: rng
321 type(nam_type),
intent(inout) :: nam
322 type(geom_type),
intent(in) :: geom
323 type(bpar_type),
intent(in) :: bpar
324 type(io_type),
intent(in) :: io
325 type(ens_type),
intent(in) :: ens
326 type(ens_type),
intent(inout) :: ensu
329 integer :: il0i,i_s,ic0a,ic2b,ic2,ie,ie_sub,ic0,jl0,il0,isub,ic1,ic1a,iv,jv,offset,nc1a
330 real(kind_real) :: fld(geom%nc0a,geom%nl0)
331 real(kind_real) :: auto_avg(nam%nc2,geom%nl0,geom%nl0),cross_avg(nam%nc2,geom%nl0,geom%nl0),auto_inv(geom%nl0,geom%nl0)
332 real(kind_real) :: sbuf(2*nam%nc2*geom%nl0**2),rbuf(2*nam%nc2*geom%nl0**2)
333 real(kind_real),
allocatable :: list_auto(:),list_cross(:),auto_avg_tmp(:,:)
334 real(kind_real),
allocatable :: fld_1(:,:),fld_2(:,:),auto(:,:,:,:),cross(:,:,:,:)
335 logical :: valid,mask_unpack(geom%nl0,geom%nl0)
338 write(mpl%info,
'(a)')
'-------------------------------------------------------------------' 339 write(mpl%info,
'(a,i5,a)')
'--- Setup sampling (nc1 = ',nam%nc1,
')' 341 call vbal%samp%setup_sampling(mpl,rng,nam,geom,bpar,io,ens)
344 write(mpl%info,
'(a)')
'-------------------------------------------------------------------' 345 write(mpl%info,
'(a)')
'--- Compute MPI distribution, halos A' 347 call vbal%samp%compute_mpi_a(mpl,nam,geom)
350 write(mpl%info,
'(a)')
'-------------------------------------------------------------------' 351 write(mpl%info,
'(a)')
'--- Compute MPI distribution, halos A-B' 353 call vbal%samp%compute_mpi_ab(mpl,nam,geom)
359 allocate(fld_1(vbal%samp%nc1a,geom%nl0))
360 allocate(fld_2(vbal%samp%nc1a,geom%nl0))
361 allocate(auto(vbal%samp%nc1a,geom%nl0,geom%nl0,ens%nsub))
362 allocate(cross(vbal%samp%nc1a,geom%nl0,geom%nl0,ens%nsub))
363 if (.not.
diag_auto)
allocate(auto_avg_tmp(geom%nl0,geom%nl0))
364 call vbal%alloc(mpl,nam,geom,bpar)
374 do i_s=1,vbal%samp%h(il0i)%n_s
375 ic0a = vbal%samp%h(il0i)%row(i_s)
376 vbal%h_n_s(ic0a,il0i) = vbal%h_n_s(ic0a,il0i)+1
377 vbal%h_c2b(vbal%h_n_s(ic0a,il0i),ic0a,il0i) = vbal%samp%h(il0i)%col(i_s)
378 vbal%h_S(vbal%h_n_s(ic0a,il0i),ic0a,il0i) = vbal%samp%h(il0i)%S(i_s)
384 if (bpar%vbal_block(iv,jv))
then 386 write(mpl%info,
'(a7,a)')
'',
'Unbalancing: '//trim(nam%varname(iv))//
' with respect to unbalanced '//trim(nam%varname(jv))
392 if (ensu%nsub==1)
then 393 write(mpl%info,
'(a10,a)',advance=
'no')
'',
'Full ensemble, member:' 395 write(mpl%info,
'(a10,a,i4,a)',advance=
'no')
'',
'Sub-ensemble ',isub,
', member:' 400 do ie_sub=1,ensu%ne/ensu%nsub
401 write(mpl%info,
'(i4)',advance=
'no') ie_sub
405 ie = ie_sub+(isub-1)*ensu%ne/ensu%nsub
410 do ic1a=1,vbal%samp%nc1a
412 ic1 = vbal%samp%c1a_to_c1(ic1a)
414 if (vbal%samp%c1l0_log(ic1,il0))
then 416 ic0 = vbal%samp%c1_to_c0(ic1)
417 ic0a = geom%c0_to_c0a(ic0)
420 fld_1(ic1a,il0) = ensu%fld(ic0a,il0,iv,1,ie)
421 fld_2(ic1a,il0) = ensu%fld(ic0a,il0,jv,1,ie)
431 auto(:,jl0,il0,isub) = auto(:,jl0,il0,isub)+fld_2(:,il0)*fld_2(:,jl0)
432 cross(:,jl0,il0,isub) = cross(:,jl0,il0,isub)+fld_1(:,il0)*fld_2(:,jl0)
437 write(mpl%info,
'(a)')
'' 442 write(mpl%info,
'(a10,a)',advance=
'no')
'',
'Average covariances: ' 444 call mpl%prog_init(nam%nc2)
451 allocate(list_auto(vbal%samp%nc1a))
452 allocate(list_cross(vbal%samp%nc1a))
456 do ic1a=1,vbal%samp%nc1a
458 ic1 = vbal%samp%c1a_to_c1(ic1a)
461 valid = vbal%samp%c1l0_log(ic1,il0).and.vbal%samp%c1l0_log(ic1,jl0).and.vbal%samp%vbal_mask(ic1,ic2)
468 list_auto(nc1a) = sum(auto(ic1a,jl0,il0,:))/
real(ensu%nsub,kind_real)
469 list_cross(nc1a) = sum(cross(ic1a,jl0,il0,:))/
real(ensu%nsub,kind_real)
475 auto_avg(ic2,jl0,il0) = sum(list_auto(1:nc1a))
476 cross_avg(ic2,jl0,il0) = sum(list_cross(1:nc1a))
478 auto_avg(ic2,jl0,il0) = 0.0
479 cross_avg(ic2,jl0,il0) = 0.0
483 deallocate(list_auto)
484 deallocate(list_cross)
490 call mpl%prog_print(ic2)
492 write(mpl%info,
'(a)')
'100%' 496 write(mpl%info,
'(a10,a)')
'',
'Gather data' 498 if (mpl%nproc>1)
then 502 sbuf(offset+1:offset+geom%nl0**2) = pack(auto_avg(ic2,:,:),.true.)
503 offset = offset+geom%nl0**2
504 sbuf(offset+1:offset+geom%nl0**2) = pack(cross_avg(ic2,:,:),.true.)
505 offset = offset+geom%nl0**2
509 call mpl%f_comm%allreduce(sbuf,rbuf,fckit_mpi_sum())
514 auto_avg(ic2,:,:) = unpack(rbuf(offset+1:offset+geom%nl0**2),mask_unpack,auto_avg(ic2,:,:))
515 offset = offset+geom%nl0**2
516 cross_avg(ic2,:,:) = unpack(rbuf(offset+1:offset+geom%nl0**2),mask_unpack,cross_avg(ic2,:,:))
517 offset = offset+geom%nl0**2
522 write(mpl%info,
'(a10,a)',advance=
'no')
'',
'Compute regressions: ' 524 call mpl%prog_init(vbal%samp%nc2b)
525 do ic2b=1,vbal%samp%nc2b
527 ic2 = vbal%samp%c2b_to_c2(ic2b)
533 if (auto_avg(ic2,il0,il0)>0.0) auto_inv(il0,il0) = 1.0/auto_avg(ic2,il0,il0)
537 auto_avg_tmp = auto_avg(ic2,:,:)
538 call syminv(mpl,geom%nl0,auto_avg_tmp,auto_inv)
542 vbal%blk(iv,jv)%auto(ic2b,:,:) = auto_avg(ic2,:,:)
543 vbal%blk(iv,jv)%cross(ic2b,:,:) = cross_avg(ic2,:,:)
544 vbal%blk(iv,jv)%auto_inv(ic2b,:,:) = auto_inv
545 vbal%blk(iv,jv)%reg(ic2b,:,:) = matmul(cross_avg(ic2,:,:),auto_inv)
548 call mpl%prog_print(ic2b)
550 write(mpl%info,
'(a)')
'100%' 556 if (any(bpar%vbal_block(iv,1:iv-1)))
then 557 write(mpl%info,
'(a10,a)',advance=
'no')
'',
'Unbalance ensemble members: ' 560 write(mpl%info,
'(i4)',advance=
'no') ie
563 if (bpar%vbal_block(iv,jv))
then 564 fld = ensu%fld(:,:,jv,1,ie)
565 call vbal%blk(iv,jv)%apply(geom,vbal%np,vbal%h_n_s,vbal%h_c2b,vbal%h_S,fld)
566 ensu%fld(:,:,iv,1,ie) = ensu%fld(:,:,iv,1,ie)-fld
570 write(mpl%info,
'(a)')
'' 576 call vbal%write(mpl,nam,geom,bpar)
589 class(vbal_type),
intent(inout) :: vbal
590 type(mpl_type),
intent(inout) :: mpl
591 type(rng_type),
intent(inout) :: rng
592 type(nam_type),
intent(inout) :: nam
593 type(geom_type),
intent(in) :: geom
594 type(bpar_type),
intent(in) :: bpar
597 call vbal%test_inverse(mpl,rng,nam,geom,bpar)
600 call vbal%test_adjoint(mpl,rng,nam,geom,bpar)
613 class(vbal_type),
intent(in) :: vbal
614 type(nam_type),
intent(in) :: nam
615 type(geom_type),
intent(in) :: geom
616 type(bpar_type),
intent(in) :: bpar
617 real(kind_real),
intent(inout) :: fld(geom%nc0a,geom%nl0,nam%nv)
621 real(kind_real) :: fld_tmp(geom%nc0a,geom%nl0),fld_out(geom%nc0a,geom%nl0,nam%nv)
629 if (bpar%vbal_block(iv,jv))
then 630 fld_tmp = fld(:,:,jv)
631 call vbal%blk(iv,jv)%apply(geom,vbal%np,vbal%h_n_s,vbal%h_c2b,vbal%h_S,fld_tmp)
632 fld_out(:,:,iv) = fld_out(:,:,iv)+fld_tmp
651 class(vbal_type),
intent(in) :: vbal
652 type(nam_type),
intent(in) :: nam
653 type(geom_type),
intent(in) :: geom
654 type(bpar_type),
intent(in) :: bpar
655 real(kind_real),
intent(inout) :: fld(geom%nc0a,geom%nl0,nam%nv)
659 real(kind_real) :: fld_tmp(geom%nc0a,geom%nl0),fld_out(geom%nc0a,geom%nl0,nam%nv)
667 if (bpar%vbal_block(iv,jv))
then 668 fld_tmp = fld_out(:,:,jv)
669 call vbal%blk(iv,jv)%apply(geom,vbal%np,vbal%h_n_s,vbal%h_c2b,vbal%h_S,fld_tmp)
670 fld_out(:,:,iv) = fld_out(:,:,iv)-fld_tmp
689 class(vbal_type),
intent(in) :: vbal
690 type(nam_type),
intent(in) :: nam
691 type(geom_type),
intent(in) :: geom
692 type(bpar_type),
intent(in) :: bpar
693 real(kind_real),
intent(inout) :: fld(geom%nc0a,geom%nl0,nam%nv)
697 real(kind_real) :: fld_tmp(geom%nc0a,geom%nl0),fld_out(geom%nc0a,geom%nl0,nam%nv)
705 if (bpar%vbal_block(iv,jv))
then 706 fld_tmp = fld(:,:,iv)
707 call vbal%blk(iv,jv)%apply_ad(geom,vbal%np,vbal%h_n_s,vbal%h_c2b,vbal%h_S,fld_tmp)
708 fld_out(:,:,jv) = fld_out(:,:,jv)+fld_tmp
727 class(vbal_type),
intent(in) :: vbal
728 type(nam_type),
intent(in) :: nam
729 type(geom_type),
intent(in) :: geom
730 type(bpar_type),
intent(in) :: bpar
731 real(kind_real),
intent(inout) :: fld(geom%nc0a,geom%nl0,nam%nv)
735 real(kind_real) :: fld_tmp(geom%nc0a,geom%nl0),fld_out(geom%nc0a,geom%nl0,nam%nv)
743 if (bpar%vbal_block(iv,jv))
then 744 fld_tmp = fld_out(:,:,iv)
745 call vbal%blk(iv,jv)%apply_ad(geom,vbal%np,vbal%h_n_s,vbal%h_c2b,vbal%h_S,fld_tmp)
746 fld_out(:,:,jv) = fld_out(:,:,jv)-fld_tmp
765 class(vbal_type),
intent(in) :: vbal
766 type(mpl_type),
intent(in) :: mpl
767 type(rng_type),
intent(inout) :: rng
768 type(nam_type),
intent(in) :: nam
769 type(geom_type),
intent(in) :: geom
770 type(bpar_type),
intent(in) :: bpar
773 real(kind_real) :: mse,mse_tot
774 real(kind_real),
allocatable :: fld(:,:,:),fld_save(:,:,:)
777 allocate(fld(geom%nc0a,geom%nl0,nam%nv))
778 allocate(fld_save(geom%nc0a,geom%nl0,nam%nv))
781 call rng%rand_real(0.0_kind_real,1.0_kind_real,fld_save)
785 call vbal%apply(nam,geom,bpar,fld)
786 call vbal%apply_inv(nam,geom,bpar,fld)
787 mse = sum((fld-fld_save)**2)
788 call mpl%f_comm%allreduce(mse,mse_tot,fckit_mpi_sum())
789 write(mpl%info,
'(a7,a,e15.8)')
'',
'Vertical balance direct/inverse test: ',mse_tot
794 call vbal%apply_inv(nam,geom,bpar,fld)
795 call vbal%apply(nam,geom,bpar,fld)
796 mse = sum((fld-fld_save)**2)
797 call mpl%f_comm%allreduce(mse,mse_tot,fckit_mpi_sum())
798 write(mpl%info,
'(a7,a,e15.8)')
'',
'Vertical balance inverse/direct test: ',mse_tot
803 call vbal%apply_ad(nam,geom,bpar,fld)
804 call vbal%apply_inv_ad(nam,geom,bpar,fld)
805 mse = sum((fld-fld_save)**2)
806 call mpl%f_comm%allreduce(mse,mse_tot,fckit_mpi_sum())
807 write(mpl%info,
'(a7,a,e15.8)')
'',
'Vertical balance direct/inverse (adjoint) test: ',mse_tot
812 call vbal%apply_inv_ad(nam,geom,bpar,fld)
813 call vbal%apply_ad(nam,geom,bpar,fld)
814 mse = sum((fld-fld_save)**2)
815 call mpl%f_comm%allreduce(mse,mse_tot,fckit_mpi_sum())
816 write(mpl%info,
'(a7,a,e15.8)')
'',
'Vertical balance inverse/direct (adjoint) test: ',mse_tot
830 class(vbal_type),
intent(in) :: vbal
831 type(mpl_type),
intent(in) :: mpl
832 type(rng_type),
intent(inout) :: rng
833 type(nam_type),
intent(in) :: nam
834 type(geom_type),
intent(in) :: geom
835 type(bpar_type),
intent(in) :: bpar
839 real(kind_real) :: sum1,sum2
840 real(kind_real),
allocatable :: fld1_blk(:,:,:),fld1_dir(:,:,:),fld1_inv(:,:,:),fld1_save(:,:,:)
841 real(kind_real),
allocatable :: fld2_blk(:,:,:),fld2_dir(:,:,:),fld2_inv(:,:,:),fld2_save(:,:,:)
844 allocate(fld1_dir(geom%nc0a,geom%nl0,nam%nv))
845 allocate(fld2_dir(geom%nc0a,geom%nl0,nam%nv))
846 allocate(fld1_inv(geom%nc0a,geom%nl0,nam%nv))
847 allocate(fld2_inv(geom%nc0a,geom%nl0,nam%nv))
848 allocate(fld1_save(geom%nc0a,geom%nl0,nam%nv))
849 allocate(fld2_save(geom%nc0a,geom%nl0,nam%nv))
852 call rng%rand_real(0.0_kind_real,1.0_kind_real,fld1_save)
853 call rng%rand_real(0.0_kind_real,1.0_kind_real,fld2_save)
860 if (bpar%vbal_block(iv,jv))
then 861 call vbal%blk(iv,jv)%apply(geom,vbal%np,vbal%h_n_s,vbal%h_c2b,vbal%h_S,fld1_blk(:,:,iv))
862 call vbal%blk(iv,jv)%apply_ad(geom,vbal%np,vbal%h_n_s,vbal%h_c2b,vbal%h_S,fld2_blk(:,:,iv))
863 call mpl%dot_prod(fld1_blk(:,:,iv),fld2_save(:,:,iv),sum1)
864 call mpl%dot_prod(fld2_blk(:,:,iv),fld1_save(:,:,iv),sum2)
865 write(mpl%info,
'(a7,a,e15.8,a,e15.8,a,e15.8)')
'',
'Vertical balance block adjoint test: ', &
866 & sum1,
' / ',sum2,
' / ',2.0*abs(sum1-sum2)/abs(sum1+sum2)
875 call vbal%apply(nam,geom,bpar,fld1_dir)
876 call vbal%apply_ad(nam,geom,bpar,fld2_dir)
881 call vbal%apply_inv(nam,geom,bpar,fld1_inv)
882 call vbal%apply_inv_ad(nam,geom,bpar,fld2_inv)
885 call mpl%dot_prod(fld1_dir,fld2_save,sum1)
886 call mpl%dot_prod(fld2_dir,fld1_save,sum2)
887 write(mpl%info,
'(a7,a,e15.8,a,e15.8,a,e15.8)')
'',
'Vertical balance direct adjoint test: ', &
888 & sum1,
' / ',sum2,
' / ',2.0*abs(sum1-sum2)/abs(sum1+sum2)
890 call mpl%dot_prod(fld1_inv,fld2_save,sum1)
891 call mpl%dot_prod(fld2_inv,fld1_save,sum2)
892 write(mpl%info,
'(a7,a,e15.8,a,e15.8,a,e15.8)')
'',
'Vertical balance inverse adjoint test: ', &
893 & sum1,
' / ',sum2,
' / ',2.0*abs(sum1-sum2)/abs(sum1+sum2)
subroutine vbal_dealloc(vbal, nam)
subroutine vbal_apply_inv(vbal, nam, geom, bpar, fld)
subroutine vbal_alloc(vbal, mpl, nam, geom, bpar)
subroutine vbal_test_inverse(vbal, mpl, rng, nam, geom, bpar)
subroutine vbal_apply(vbal, nam, geom, bpar, fld)
subroutine vbal_apply_ad(vbal, nam, geom, bpar, fld)
logical, parameter diag_auto
real(kind_real), parameter var_th
subroutine vbal_write(vbal, mpl, nam, geom, bpar)
subroutine vbal_run_vbal(vbal, mpl, rng, nam, geom, bpar, io, ens, ensu)
subroutine vbal_run_vbal_tests(vbal, mpl, rng, nam, geom, bpar)
subroutine vbal_read(vbal, mpl, nam, geom, bpar)
subroutine vbal_test_adjoint(vbal, mpl, rng, nam, geom, bpar)
integer, parameter, public kind_real
subroutine vbal_apply_inv_ad(vbal, nam, geom, bpar, fld)