KronLinInv  0.3
Kronecker-product-based linear inversion

◆ bandpostcov()

subroutine, public ompi_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
30/1/2017 - OpenMPI version

Definition at line 753 of file ompi_kronlininv.f08.

753  !!
754  !! Calculate a band of the posterior covariance
755  !!
756  real(dp),intent(in) :: u1(:,:),u2(:,:),u3(:,:),iucm1(:,:), &
757  iucm2(:,:),iucm3(:,:)
758  !! diaginvlambda = (I + lam1 x lam2 x lam3 )^-1
759  real(dp),intent(in) :: diaginvlambda(:) !! diagonal/vector central factor
760  real(dp),intent(inout) :: bandpostc(:,:)
761  integer,intent(in) :: lowdiag, updiag
762 
763  integer :: a,b
764  real(dp),allocatable :: row2(:),col1(:),recvrow(:),bandpostcmpi(:)
765  integer :: nr12,nc1
766  integer :: ni,nj,nk,nl,nm,nn,na,nb
767 
768  real(dp) :: firststartt,startt
769  integer,allocatable :: av(:)!,bv(:)
770  integer,allocatable :: iv(:),jv(:),kv(:) !,lv(:),mv(:),nv(:)
771  integer :: p,aband,aend,bband,astart,d,bband1,bband2,ntota,everynit,mytotit
772  integer,allocatable :: scheduling(:),looping(:,:)
773  character(len=30) :: loopinfo
774  character(len=12) :: dnum
775 
776  ni = size(u1,1)
777  nl = size(u1,2)
778  nj = size(u2,1)
779  nm = size(u2,2)
780  nk = size(u3,1)
781  nn = size(u3,2)
782  na = ni*nj*nk
783  nb = nl*nm*nn
784 
785  if (na /= nb) then
786  write(*,*) '(Na /= Nb)', na,nb
787  stop
788  end if
789  if ( (updiag>=na) .or. (lowdiag>=na) .or. (lowdiag<0) .or. (updiag<0) ) then
790  write(*,*) .or."(updiag<Na) (lowdiag<Na)"
791  write(*,*) "updiag",updiag,"Na",na,"lowdiag",lowdiag,"Na",na
792  stop
793  end if
794 
795  !! vectorize row and col calculations for Kron prod AxBxC
796  allocate(av(na),iv(na),jv(na),kv(na))
797  !allocate(bv(Nb),lv(Nb),mv(Nb),nv(Nb))
798  forall(p = 1:na) av(p) = p
799  !forall(p = 1:Nb) bv(p) = p
800 
801  !! vectors containing all possible indices for
802  !! row calculations of Kron prod AxBxC
803  iv = (av-1)/(nk*nj)+1
804  jv = (av-1-(iv-1)*nk*nj)/nk+1
805  kv = av-(jv-1)*nk-(iv-1)*nk*nj
806  !! vectors containing all possible indices for
807  !! column calculations of Kron prod AxBxC
808  ! lv = (bv-1)/(Nn*Nm) + 1
809  ! mv = (bv-1-(lv-1)*Nn*Nm)/Nn + 1
810  ! nv = bv-(mv-1)*Nn-(lv-1)*Nn*Nm
811 
812  !! allocate stuff
813  nr12 = size(u1,2)* size(u2,2)* size(u3,2)
814  nc1 = size(iucm1,1)* size(iucm2,1)* size(iucm3,1)
815  allocate(row2(nr12),col1(nc1))
816 
817  ! Lapack: http://www.netlib.org/lapack/lug/node124.html
818  ! aij is stored in AB(ku+1+i-j,j) for max(1,j-ku) <= i <= \min(m,j+kl).
819  !------------
820  ! Diagonals of a matrix
821  ! i + d = j
822  ! main diag d = 0
823  ! upper d > 0
824  ! lower d < 0
825  ! diagonals of a matrix and indices of related band matrix
826  ! ONLY for square matrix
827 
828  !!---------------------------------
829  firststartt = mpi_wtime()
830  ! !! calculate scheduling for a
831  ! call spreadwork(ntota,numcpus,scheduling,looping,1)
832  ! allocate(postcmpi(scheduling(myrank+1),ntotb),recvrow(ntotb),sendrow(ntotb))
833  ! mytotit = looping(myrank+1,2)-looping(myrank+1,1)+1
834 
835  allocate(bandpostcmpi(size(bandpostc,2)), recvrow(size(bandpostc,2)))
836  ! initialize postC
837 
838  bandpostc = 0.0_dp
839 
840  do d=-lowdiag,updiag
841  call para_barrier()
842 
843  !!--------------------------
844  if (d<0) then
845  astart = abs(d)+1
846  else
847  astart = 1
848  end if
849  if (d>0) then
850  aend = na-abs(d)
851  else
852  aend = na
853  end if
854  !print*,'diagonal',d
855 
856  !! calculate scheduling for a
857  ntota = aend-astart+1
858  call spreadwork(ntota,numcpus,scheduling,looping,astart)
859  if (ntota<1000) then
860  everynit = ntota/100
861  else
862  everynit = ntota/1000
863  end if
864 
865  write(dnum,"(i9)") d
866  loopinfo = "bandpostcov() diag "//trim(dnum)//" "
867  startt = mpi_wtime()
868  if (myrank==masterrank) write(output_unit,*)
869  !! indices of normal matrix
870  bandpostcmpi(:) = 0.0_dp
871  aband = updiag+1-d !! aband is constant within this loop
872  do a=looping(myrank+1,1),looping(myrank+1,2) !!astart,aend
873  !! info
874  if ( (myrank==masterrank) .and. (mod(a,everynit)==0) ) then
875  call timeinfo(scheduling(myrank+1),a-astart+1,startt,loopinfo)
876  end if
877 
878  !if ( (myrank==masterrank) .and. (mod(a,250)==0) ) print*,"d",d,"a",a
879  !!--------------------------------------------------------
880  b = a+d
881  !! indices of the band matrix
882  !aband = updiag+1+a-b
883  !bband = b
884  !!--------------------------------------------------------
885 
886  !!----------------------------------------------------------------
887  ! row first two factors
888  row2 = diaginvlambda * u1(iv(a),iv) * u2(jv(a),jv) * u3(kv(a),kv)
889 
890  !! calculate one row of first TWO factors
891  !!call columnAxBxC(Ni,Nj,Nk,Nl,Nm,Nn, iUCm1,iUCm2,iUCm3,b,col1)
892  col1 = iucm1(iv,iv(b)) * iucm2(jv,jv(b)) * iucm3(kv,kv(b))
893 
894  !! calculate one element of the posterior covariance
895  !! store it in the band storage format
896  !!bandpostC(aband,bband) = sum(row2*col1)
897  bandpostcmpi(b) = sum(row2*col1)
898  !print*, a,b,aband,bband,bandpostC(aband,bband)
899  !!----------------------------------------------------------------
900 
901  end do ! a=astart,aend
902 
903  !! send/recv rows
904  !! collect all results in masterrank
905 
906 
907  bband1 = looping(myrank+1,1)+d !!b = a+d
908  bband2 = looping(myrank+1,2)+d
909 
910  call para_gathv1ddp(scheduling, looping(:,1)-1, masterrank, &
911  bandpostcmpi(bband1:bband2), recvrow )
912  if (myrank==masterrank) bandpostc(aband,:) = recvrow
913 
914 
915  end do
916 
integer, parameter, public masterrank
subroutine para_barrier()
subroutine para_gathv1ddp(recvcounts, displs, receiver, sendbuf, recvbuf)
integer, public, protected myrank
subroutine spreadwork(nit, nunits, scheduling, looping, startpoint)
integer, public, protected numcpus
subroutine timeinfo(totit, curit, startt, loopinfo)
Here is the caller graph for this function: