KronLinInv  0.3
Kronecker-product-based linear inversion

◆ posteriormean()

subroutine, public ompi_kronlininv::posteriormean ( 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)  Z1,
real(dp), dimension(:,:), intent(in)  Z2,
real(dp), dimension(:,:), intent(in)  Z3,
real(dp), dimension(:,:), intent(in)  G1,
real(dp), dimension(:,:), intent(in)  G2,
real(dp), dimension(:,:), intent(in)  G3,
real(dp), dimension(:), intent(in)  mprior,
real(dp), dimension(:), intent(in)  dobs,
real(dp), dimension(:), intent(out)  postm 
)

Computes the posterior mean

Parameters
[in]U1,U2,U3\( \mathbf{U}_1 \), \( \mathbf{U}_2 \), \( \mathbf{U}_3 \) of \( F_{\sf{A}} \)
[in]diaginvlambda\( F_{\sf{B}} \)
[in]Z1,Z2,Z3\( \mathbf{U}_1^{-1} \mathbf{C}_{\rm{M}}^{\rm{x}} (\mathbf{G}^{\rm{x}})^{\sf{T}}(\mathbf{C}_{\rm{D}}^{\rm{x}})^{-1} \), \( \mathbf{U}_2^{-1} \mathbf{C}_{\rm{M}}^{\rm{y}} (\mathbf{G}^{\rm{y}})^{\sf{T}} (\mathbf{C}_{\rm{D}}^{\rm{y}})^{-1}\), \( \mathbf{U}_3^{-1} \mathbf{C}_{\rm{M}}^{\rm{z}} (\mathbf{G}^{\rm{z}})^{\sf{T}} (\mathbf{C}_{\rm{D}}^{\rm{z}})^{-1} \) of \( F_{\sf{D}} \)
[in]G1,G2,G3The 3 forward modeling matrices \( \mathbf{G} = \mathbf{G_1} \otimes \mathbf{G_2} \otimes \mathbf{G_3} \)
[in]mpriorPrior model (vector)
[in]dobsObserved data (vector)
[out]postmCalculated posterior mean model (vector)
Date
5/8/2016 - Initial Version
27/12/2016 - New ETA calculations
18/1/2017 - OpenMPI version

Definition at line 949 of file ompi_kronlininv.f08.

949 
950  !!
951  use parautil
952 
953  !!
954  !! Calculate the posterior mean model
955  !!
956  real(dp),intent(in) :: u1(:,:),u2(:,:),u3(:,:), g1(:,:),g2(:,:),g3(:,:)
957  real(dp),intent(in) :: z1(:,:),z2(:,:),z3(:,:)
958  real(dp),intent(in) :: mprior(:),dobs(:),diaginvlambda(:)
959  real(dp),intent(out) :: postm(:)
960 
961  real(dp),allocatable :: ddiff(:),ddiffmpi(:),postmmpi(:)
962  integer :: a,b,na,nb
963  integer :: ni,nj,nk,nl,nm,nn
964 
965  integer,allocatable :: av(:),bv(:)
966  integer,allocatable :: iv(:),jv(:),kv(:),lv(:),mv(:),nv(:)
967  !! ivo(:),jvo(:),kvo(:)
968  integer :: p,everynit
969 
970  real(dp),allocatable :: zh(:),eludzh(:),zhmpi(:),eludzhmpi(:)
971 
972  integer :: ia,ib
973  real(dp) :: startt,firststartt,endt
974  character(len=30) :: loopinfo
975 
976  integer ::curit,totit
977  integer,allocatable :: scheduling(:),looping(:,:)
978 
979  !! sizes
980  ni = size(z1,1)
981  nl = size(z1,2)
982  nj = size(z2,1)
983  nm = size(z2,2)
984  nk = size(z3,1)
985  nn = size(z3,2)
986 
987  !! sizes
988  ! Nr12 = size(U1,2)*size(U2,2)*size(U3,2)
989  ! Nc1 = size(Z1,1)*size(Z2,1)*size(Z3,1)
990  na = size(mprior,1)
991  nb = size(dobs,1)
992 
993  !! allocate stuff
994  allocate(ddiff(nb))
995  allocate(zh(na),eludzh(na))
996 
997  !! vectorize row and col calculations for Kron prod AxBxC
998  !!allocate(ivo(Nb),jvo(Nb),kvo(Nb))
999  allocate(av(na),iv(na),jv(na),kv(na))
1000  allocate(bv(nb),lv(nb),mv(nb),nv(nb))
1001  forall(p = 1:na) av(p) = p
1002  forall(p = 1:nb) bv(p) = p
1003 
1004  !! vectors containing all possible indices for
1005  !! row calculations of Kron prod AxBxC
1006  iv = (av-1)/(nk*nj)+1
1007  jv = (av-1-(iv-1)*nk*nj)/nk+1
1008  kv = av-(jv-1)*nk-(iv-1)*nk*nj
1009  !! vectors containing all possible indices for
1010  !! column calculations of Kron prod AxBxC
1011  lv = (bv-1)/(nn*nm) + 1
1012  mv = (bv-1-(lv-1)*nn*nm)/nn + 1
1013  nv = bv-(mv-1)*nn-(lv-1)*nn*nm
1014  !! Gs have different shape than Us !!
1015 
1016  !!#######################
1017  if (na<1000)then
1018  everynit = na/50
1019  else if (na<100000) then
1020  everynit = na/100
1021  else
1022  everynit = na/1000
1023  end if
1024 
1025  !!---------------------------------
1026  firststartt = mpi_wtime()
1027 
1028  !!#######################
1029  !!# dobs - dcalc #
1030  !!#######################
1031  startt = mpi_wtime()
1032  loopinfo = "posteriormean(): loop 1/3"
1033  if (myrank==masterrank) write(output_unit,*)
1034  !! calculate scheduling for Nb
1035  call spreadwork(nb,numcpus,scheduling,looping,1)
1036  allocate(ddiffmpi(scheduling(myrank+1)))
1037  !! difference obs-calc data
1038  totit = looping(myrank+1,2)-looping(myrank+1,1)
1039  do b=looping(myrank+1,1),looping(myrank+1,2) !! rank starts from 0
1040  curit = (b-looping(myrank+1,1)+1)
1041  if ( (myrank==masterrank) .and. (mod( curit,everynit)==0) ) then
1042  call timeinfo(totit,curit,startt,loopinfo)
1043  end if
1044 
1045  !!--------------------------------------------------------------------------------
1046  ib = b - looping(myrank+1,1) + 1
1047  ddiffmpi(ib) = dobs(b) - sum(mprior * g1(lv(b),iv) * g2(mv(b),jv) * g3(nv(b),kv))
1048  !!--------------------------------------------------------------------------------
1049 
1050  end do
1051 
1052  startt = mpi_wtime()
1053  !! assemble full ddfiff and broadcast it
1054  !! displacements must start from 0, not 1, so looping-1
1055  call para_allgathv1ddp( scheduling,looping(:,1)-1, ddiffmpi, ddiff )
1056  if (myrank==masterrank) then
1057  print*,"time for first allgatherv:",mpi_wtime()-startt,"s"
1058  end if
1059 
1060 
1061  !!#######################
1062  !!# === U d Z h === #
1063  !!#######################
1064  startt = mpi_wtime()
1065  !! calculate scheduling for Na
1066  loopinfo = "posteriormean(): loop 2/3"
1067  if (myrank==masterrank) write(output_unit,*)
1068  call spreadwork(na,numcpus,scheduling,looping,1)
1069  allocate(zhmpi(scheduling(myrank+1)))
1070  totit = looping(myrank+1,2)-looping(myrank+1,1)
1071  do a=looping(myrank+1,1),looping(myrank+1,2) !! rank starts from 0
1072  curit =(a-looping(myrank+1,1)+1)
1073  if ( ( myrank==masterrank ) .and. (mod( curit,everynit)==0) ) then
1074  call timeinfo(totit,curit,startt,loopinfo)
1075  end if
1076 
1077  !!---------------------------------------------------------------------------
1078  ia = a - looping(myrank+1,1) + 1
1079  zhmpi(ia) = sum( z1(iv(a),lv) * z2(jv(a),mv) * z3(kv(a),nv) * ddiff )
1080  !!---------------------------------------------------------------------------
1081 
1082  end do
1083 
1084  startt = mpi_wtime()
1085  !! assemble full Zh and broadcast it
1086  call para_allgathv1ddp( scheduling,looping(:,1)-1, zhmpi, zh )
1087  if (myrank==masterrank) then
1088  print*,"time for second allgatherv:",mpi_wtime()-startt,"s"
1089  end if
1090 
1091  !!-----------------------------------------------
1092  !! Second loop
1093  !!### need to re-loop because full Zh is needed
1094  !!#######################
1095  !!# post(a) #
1096  !!#######################
1097  startt = mpi_wtime()
1098  !! calculate scheduling for Na
1099  loopinfo = "posteriormean(): loop 3/3"
1100  if (myrank==masterrank) write(output_unit,*)
1101  call spreadwork(na,numcpus,scheduling,looping,1)
1102  allocate(eludzhmpi(scheduling(myrank+1)),postmmpi(scheduling(myrank+1)))
1103  totit = looping(myrank+1,2)-looping(myrank+1,1)
1104  do a=looping(myrank+1,1),looping(myrank+1,2) !! rank starts from 0
1105  curit = (a-looping(myrank+1,1)+1)
1106  if ( ( myrank==masterrank ) .and. (mod(curit,everynit)==0) ) then
1107  call timeinfo(totit,curit,startt,loopinfo)
1108  end if
1109 
1110  !!--------------------------------------------------------------------------------------
1111  ia = a - looping(myrank+1,1) + 1
1112  !!
1113  eludzhmpi(ia) = sum( u1(iv(a),iv) * u2(jv(a),jv) * u3(kv(a),kv) * diaginvlambda * zh )
1114  !! element of the posterior mean
1115  postmmpi(ia) = mprior(a) + eludzhmpi(ia)
1116  !!--------------------------------------------------------------------------------------
1117 
1118  end do
1119 
1120  startt = mpi_wtime()
1121  !! assemble full postm only for masterrank
1122  call para_gathv1ddp( scheduling,looping(:,1)-1, masterrank, postmmpi, postm )
1123  if (myrank==masterrank) then
1124  print*,"time for third allgatherv:",mpi_wtime()-startt,"s"
1125  end if
1126 
1127 
1128  if (myrank==masterrank) then
1129  write(output_unit,*)
1130  write(output_unit,*)
1131  endt = MPI_Wtime()
1132  print*,"posteriormean():",endt-firststartt," MPI wall clock time"
1133  end if
1134 
1135  !print*,myrank,":",shape(ddiffmpi),shape(Zhmpi),shape(elUDZhmpi),shape(postmmpi),&
1136  ! shape(ddiff),shape(Zh),shape(elUDZh),shape(postm)
1137 
1138  return
integer, parameter, public masterrank
subroutine para_gathv1ddp(recvcounts, displs, receiver, sendbuf, recvbuf)
integer, public, protected myrank
subroutine spreadwork(nit, nunits, scheduling, looping, startpoint)
integer, public, protected numcpus
subroutine para_allgathv1ddp(scheduling, displs, sendbuf, recvbuf)
subroutine timeinfo(totit, curit, startt, loopinfo)
Subroutines/utilities for the parallel version of KronLinInv using OpenMPI.
Here is the call graph for this function:
Here is the caller graph for this function: