KronLinInv  0.3
Kronecker-product-based linear inversion

◆ blockpostcov()

subroutine, public kronlininv::blockpostcov ( real(dp), dimension(:,:), intent(in)  U1,
real(dp), dimension(:,:), intent(in)  U2,
real(dp), dimension(:,:), intent(in)  U3,
real(dp), dimension(:), intent(in)  diaginvlambda,
real(dp), dimension(:,:), intent(in)  iUCm1,
real(dp), dimension(:,:), intent(in)  iUCm2,
real(dp), dimension(:,:), intent(in)  iUCm3,
integer, intent(in)  astart,
integer, intent(in)  aend,
integer, intent(in)  bstart,
integer, intent(in)  bend,
real(dp), dimension(:,:), intent(out)  postC 
)

Computes a block of the posterior covariance.

Parameters
[in]U1,U2,U3\( \mathbf{U}_1 \), \( \mathbf{U}_2 \), \( \mathbf{U}_3 \) of \( F_{\sf{A}} \)
[in]diaginvlambda\( F_{\sf{B}} \)
[in]iUCm1,iUCm2,iUCm3\(\mathbf{U}_1^{-1} \mathbf{C}_{\rm{M}}^{\rm{x}}\), \(\mathbf{U}_2^{-1} \mathbf{C}_{\rm{M}}^{\rm{y}}\), \(\mathbf{U}_2^{-1} \mathbf{C}_{\rm{M}}^{\rm{z}}\) of \( F_{\sf{C}} \)
[in]astart,aendindex of first/last row of the requested block
[in]bstart,bendindex of first/last column of the requested block
[out]postCblock of the posterior covariance
Date
5/8/2016 - Initial Version
4/11/2016 - Removed indices lv,mv,kv
27/13/2016 - New ETA calculations

Definition at line 314 of file kronlininv.f08.

314  !!
315  !! Calculates a block of the posterior covariance
316  !!
317  real(dp),intent(in) :: u1(:,:),u2(:,:),u3(:,:),iucm1(:,:), &
318  iucm2(:,:),iucm3(:,:)
319  !! diaginvlambda = (I + lam1 x lam2 x lam3 )^-1
320  real(dp),intent(in) :: diaginvlambda(:) !! diagonal/vector central factor
321  real(dp),intent(out) :: postc(:,:)
322  integer,intent(in) :: astart,aend,bstart,bend
323 
324  integer :: a,b
325  real(dp),allocatable :: row1(:),row2(:),col1(:)
326  integer :: nr12,nc1
327  integer :: ni,nj,nk,nl,nm,nn,na,nb
328 
329  integer,allocatable :: av(:)!,bv(:)
330  integer,allocatable :: iv(:),jv(:),kv(:) !,lv(:),mv(:),nv(:)
331  integer :: p,csha1,csha2,everynit,nthr,privcount,totcount
332  real(dp) :: eta,frac,startt,endt
333 
334  ni = size(u1,1)
335  nl = size(u1,2)
336  nj = size(u2,1)
337  nm = size(u2,2)
338  nk = size(u3,1)
339  nn = size(u3,2)
340  na = ni*nj*nk
341  nb = nl*nm*nn
342 
343  !! check shape of output array
344  if (na /= nb) then
345  write(*,*) '(Na /= Nb)', na,nb
346  stop
347  end if
348  csha1 = aend-astart+1
349  csha2 = bend-bstart+1
350  if ( (size(postc,1)/=csha1) .or. (size(postc,2)/=csha2)) then
351  write(*,*) "Wrong size of the posterior covariance block array."
352  stop
353  end if
354  !! check limits of requested block
355  if ( (astart<1) .or. (aend>na) .or. (astart>aend) .or. &
356  (bstart<1) .or. (bend>na) .or. (bstart>bend) ) then
357  write(*,*) "Wrong size of the requested block array."
358  stop
359  end if
360 
361  !! vectorize row and col calculations for Kron prod AxBxC
362  allocate(av(na),iv(na),jv(na),kv(na))
363  !allocate(bv(Nb),lv(Nb),mv(Nb),nv(Nb))
364  forall(p = 1:na) av(p) = p
365  !forall(p = 1:Nb) bv(p) = p
366 
367  !! vectors containing all possible indices for
368  !! row calculations of Kron prod AxBxC
369  iv = (av-1)/(nk*nj)+1
370  jv = (av-1-(iv-1)*nk*nj)/nk + 1
371  kv = av-(jv-1)*nk-(iv-1)*nk*nj
372 
373  !! allocate stuff
374  nr12 = size(u1,2)* size(u2,2)* size(u3,2)
375  nc1 = size(iucm1,1)* size(iucm2,1)* size(iucm3,1)
376  allocate(row1(nr12),row2(nr12),col1(nc1))
377 
378  !!------------------------
379  if (aend-astart+1<20) then
380  everynit = 1
381  else if (aend-astart+1<100000) then
382  everynit = (aend-astart+1)/100
383  else
384  everynit = (aend-astart+1)/1000
385  end if
386 
387 
388  !!------------------------
389  !$OMP PARALLEL PRIVATE(privcount)
390  startt = omp_get_wtime()
391  nthr = omp_get_num_threads()
392 
393  totcount = aend-astart+1
394  privcount = -1
395  if ( omp_get_thread_num()==0 ) write(output_unit,*)
396  !$OMP DO PRIVATE(row2,col1,a,b)
397  do a=astart,aend
398  privcount = privcount + 1
399  if ( (omp_get_thread_num()==0 ) .and. (mod(privcount,everynit/nthr)==0) ) then
400  frac = real(privcount,dp)/(real(totcount,dp)/real(nthr,dp))
401  eta = ( (omp_get_wtime()-startt) / real(privcount,dp) ) * &
402  (real(totcount-nthr*privcount,dp)/real(nthr,dp))
403  write(output_unit,fmt='(a19,f7.3,6x,a4,f12.2,1x,a3,a5)') 'blockpostcov(): %',&
404  frac*100_dp,"ETA:",eta/60.0,"min",char(27)//'[1A'//achar(13)
405  flush(output_unit) !! to make sure it prints immediately
406  end if
407 
408  !! row first two factors
409  !! a row x diag matrix
410  !!row2 = U1(iv(a),lv) * U2(jv(a),mv) * U3(kv(a),nv) * diaginvlambda
411  row2 = u1(iv(a),iv) * u2(jv(a),jv) * u3(kv(a),kv) * diaginvlambda
412 
413  do b=bstart,bend
414 
415  !! calculate one row of first TWO factors
416  !!call columnAxBxC(Ni,Nj,Nk,Nl,Nm,Nn, iUCm1,iUCm2,iUCm3,b,col1)
417  col1 = iucm1(iv,iv(b)) * iucm2(jv,jv(b)) * iucm3(kv,kv(b))
418 
419  !! calculate one element of the posterior covariance
420  postc(a,b) = sum(row2*col1)
421 
422  end do
423  end do
424  !$OMP END DO
425  endt = omp_get_wtime()
426  !$OMP END PARALLEL
427  write(output_unit,*)
428  print*,"blockpostcov():",endt-startt," OMP wall clock time"
429 
integer, parameter, public dp