KronLinInv  0.3
Kronecker-product-based linear inversion

◆ bandpostcov()

subroutine, public kronlininv::bandpostcov ( 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)  lowdiag,
integer, intent(in)  updiag,
real(dp), dimension(:,:), intent(inout)  bandpostC 
)

Computes a band of the posterior covariance. See http://www.netlib.org/lapack/lug/node124.html

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]lowdiag,updiagLower and upper diagonal number of requested band
[out]postCband of the posterior covariance stored following Lapack convention
Date
11/8/2016 - Initial Version
4/11/2016 - Removed indices lv,mv,kv

Definition at line 453 of file kronlininv.f08.

453  !!
454  !! Calculate a band of the posterior covariance
455  !!
456  real(dp),intent(in) :: u1(:,:),u2(:,:),u3(:,:),iucm1(:,:), &
457  iucm2(:,:),iucm3(:,:)
458  !! diaginvlambda = (I + lam1 x lam2 x lam3 )^-1
459  real(dp),intent(in) :: diaginvlambda(:) !! diagonal/vector central factor
460  real(dp),intent(inout) :: bandpostc(:,:)
461  integer,intent(in) :: lowdiag, updiag
462 
463  integer :: a,b
464  real(dp),allocatable :: row1(:),row2(:),col1(:)
465  integer :: nr12,nc1
466  integer :: ni,nj,nk,nl,nm,nn,na,nb
467 
468  integer,allocatable :: av(:)!,bv(:)
469  integer,allocatable :: iv(:),jv(:),kv(:) !,lv(:),mv(:),nv(:)
470  integer :: p,aband,aend,bband,astart,d
471  integer :: nthr,privcount,everynit
472  real(dp) :: eta,frac,startt,firststartt,endt
473 
474  ni = size(u1,1)
475  nl = size(u1,2)
476  nj = size(u2,1)
477  nm = size(u2,2)
478  nk = size(u3,1)
479  nn = size(u3,2)
480  na = ni*nj*nk
481  nb = nl*nm*nn
482 
483  if (na /= nb) then
484  write(*,*) '(Na /= Nb)', na,nb
485  stop
486  end if
487  if ( (updiag>=na) .or. (lowdiag>=na) .or. (lowdiag<0) .or. (updiag<0) ) then
488  write(*,*) .or."(updiag<Na) (lowdiag<Na)"
489  write(*,*) "updiag",updiag,"Na",na,"lowdiag",lowdiag,"Na",na
490  stop
491  end if
492 
493  !! vectorize row and col calculations for Kron prod AxBxC
494  allocate(av(na),iv(na),jv(na),kv(na))
495  !allocate(bv(Nb),lv(Nb),mv(Nb),nv(Nb))
496  forall(p = 1:na) av(p) = p
497  !forall(p = 1:Nb) bv(p) = p
498 
499  !! vectors containing all possible indices for
500  !! row calculations of Kron prod AxBxC
501  iv = (av-1)/(nk*nj)+1
502  jv = (av-1-(iv-1)*nk*nj)/nk+1
503  kv = av-(jv-1)*nk-(iv-1)*nk*nj
504  !! vectors containing all possible indices for
505  !! column calculations of Kron prod AxBxC
506  ! lv = (bv-1)/(Nn*Nm) + 1
507  ! mv = (bv-1-(lv-1)*Nn*Nm)/Nn + 1
508  ! nv = bv-(mv-1)*Nn-(lv-1)*Nn*Nm
509 
510  !! allocate stuff
511  nr12 = size(u1,2)* size(u2,2)* size(u3,2)
512  nc1 = size(iucm1,1)* size(iucm2,1)* size(iucm3,1)
513  allocate(row1(nr12),row2(nr12),col1(nc1))
514 
515 
516  everynit = 250
517 
518 
519  ! Lapack: http://www.netlib.org/lapack/lug/node124.html
520  ! aij is stored in AB(ku+1+i-j,j) for max(1,j-ku) <= i <= \min(m,j+kl).
521  !------------
522  ! Diagonals of a matrix
523  ! i + d = j
524  ! main diag d = 0
525  ! upper d > 0
526  ! lower d < 0
527  ! diagonals of a matrix and indices of related band matrix
528  ! ONLY for square matrix
529 
530  ! initialize postC
531  bandpostc = 0.0_dp
532 
533  !!=====================================
534  firststartt = omp_get_wtime()
535 
536  do d=-lowdiag,updiag
537  if (d<0) then
538  astart = abs(d)+1
539  else
540  astart = 1
541  end if
542  if (d>0) then
543  aend = na-abs(d)
544  else
545  aend = na
546  end if
547  !print*,'diagonal',d
548  !! indices of normal matrix
549 
550  print*,"Diagonal ",d," from range [",-lowdiag,",",updiag,"]"
551  !-------------------------
552  !$OMP PARALLEL
553  privcount = -1
554  startt = omp_get_wtime()
555  nthr = omp_get_num_threads()
556 
557  !$OMP DO PRIVATE(row2,col1,a,b,aband,bband,privcount)
558  do a=astart,aend
559  privcount = privcount + 1
560  if ( (omp_get_thread_num()==0 ) .and. (mod(privcount,everynit/nthr)==0) ) then
561  frac = real(privcount,dp)/(real(nb,dp)/real(nthr,dp))
562  eta = ( (omp_get_wtime()-startt) / real(privcount,dp) ) * &
563  (real(aend-astart+1-nthr*privcount,dp)/real(nthr,dp))
564  write(output_unit,fmt='(a27,f7.3,6x,a4,f12.2,1x,a3,a5)') 'bandpostcov(): %',&
565  frac*100_dp,"ETA:",eta/60.0,"min",char(27)//'[1A'//achar(13)
566  flush(output_unit) !! to make sure it prints immediately
567  end if
568 
569  b = a+d
570  !! indices of the band matrix
571  aband = updiag+1+a-b
572  bband = b
573 
574  !! row first two factors
575  row2 = diaginvlambda * u1(iv(a),iv) * u2(jv(a),jv) * u3(kv(a),kv)
576 
577  !! calculate one row of first TWO factors
578  !!call columnAxBxC(Ni,Nj,Nk,Nl,Nm,Nn, iUCm1,iUCm2,iUCm3,b,col1)
579  col1 = iucm1(iv,iv(b)) * iucm2(jv,jv(b)) * iucm3(kv,kv(b))
580 
581  !! calculate one element of the posterior covariance
582  !! store it in the band storage format
583  bandpostc(aband,bband) = sum(row2*col1)
584  !print*, a,b,aband,bband,bandpostC(aband,bband)
585 
586  end do ! a=astart,aend
587  !$OMP END DO
588  endt = omp_get_wtime()
589  !$OMP END PARALLEL
590  write(output_unit,*)
591  print*,"bandpostcov():",endt-firststartt," OMP wall clock time"
592 
593  end do
594 
595 
integer, parameter, public dp