mirror of
https://github.com/HongjianFang/DSurfTomo.git
synced 2025-05-07 15:41:14 +08:00
223 lines
5.9 KiB
Fortran
223 lines
5.9 KiB
Fortran
subroutine voronoiproj(leniw,lenrw,colg,nrow,rw,dres,goxd,dvxd,gozd,dvzd,depz,&
|
|
nx,ny,nz,nd,ncells,hvratio,damp,iproj,dv)
|
|
use lsmrModule, only:lsmr
|
|
|
|
implicit none
|
|
integer leniw,lenrw
|
|
integer nx,ny,nz
|
|
! integer iw(leniw)
|
|
integer colg(lenrw),nrow(nd)
|
|
real depz(nz)
|
|
real rw(lenrw)
|
|
integer ncells,acells
|
|
real dv(*),dres(*)
|
|
real goxd,gozd,dvxd,dvzd
|
|
real damp
|
|
real hvratio,cmb
|
|
integer ndim,nd
|
|
integer iproj
|
|
|
|
real,parameter:: radius = 6371.0,ftol = 0.1,pi = 3.141592654
|
|
integer ii,ix,iy,iz
|
|
real,dimension(:),allocatable:: grow,gcol,subrow,dis,dws,xunknown
|
|
real,dimension(:),allocatable:: lat,lon,rad,theta,phi,rrad,xpts,ypts,zpts
|
|
real,dimension(:),allocatable :: rw_p,rwgp,norm
|
|
integer,dimension(:),allocatable:: iw_p,row,col,iwgp,colgp
|
|
integer idx
|
|
integer maxnar,nzid
|
|
integer iseed(4)
|
|
real xs,ys,zs
|
|
real rx
|
|
|
|
real atol,btol
|
|
real conlim
|
|
integer istop
|
|
integer itnlim
|
|
real acond
|
|
real anorm
|
|
real arnorm
|
|
real rnorm
|
|
real xnorm
|
|
integer localSize,nout,itn
|
|
integer leniw_p,lenrw_p,leniwgp,lenrwgp
|
|
integer start
|
|
|
|
allocate(lat(nx-2),lon(ny-2),rad(nz-1))
|
|
ndim = (nx-2)*(ny-2)*(nz-1)
|
|
|
|
do ii = 1,nx-2
|
|
lat(ii) = (goxd-(ii-1)*dvxd)*pi/180
|
|
enddo
|
|
|
|
do ii = 1,ny-2
|
|
lon(ii) = (gozd+(ii-1)*dvzd)*pi/180
|
|
enddo
|
|
|
|
!cmb = radius - depz(nz-1)*hvratio
|
|
do ii = 1,nz-1
|
|
rad(ii) = radius-depz(ii)*hvratio
|
|
!rad(ii) = cmb+depz(ii)*hvratio
|
|
enddo
|
|
|
|
allocate(theta(ncells),phi(ncells),rrad(ncells),norm(ncells))
|
|
allocate(xpts(ncells),ypts(ncells),zpts(ncells),dis(ncells),xunknown(ncells))
|
|
allocate(rw_p(ndim))
|
|
allocate(iw_p(2*ndim+1),row(ndim),col(ndim),dws(ndim))
|
|
|
|
iseed(1:3) = (/38,62,346/)
|
|
iseed(4) = 2*iproj+1
|
|
call slarnv(1,iseed,ncells,theta)
|
|
theta = (gozd+theta*(ny-3)*dvzd)*pi/180
|
|
call slarnv(1,iseed,ncells,phi)
|
|
phi = pi/2-(goxd-phi*(nx-3)*dvxd)*pi/180
|
|
call slarnv(1,iseed,ncells,rrad)
|
|
rrad = radius-rrad*depz(nz-1)*hvratio
|
|
|
|
! adaptive cells based on dws, assume 1/2 of all ncells are used
|
|
! as adaptive cells
|
|
dws = 0
|
|
do ii = 1,lenrw
|
|
dws(colg(ii)) = dws(colg(ii))+abs(rw(ii))
|
|
enddo
|
|
acells = int(ncells/2.0)
|
|
do ii = ncells-acells,ncells
|
|
call random_index(idx,dws)
|
|
ix = mod(idx,nx-2)
|
|
iy = idx/(nx-2)
|
|
iz = idx/((nx-2)*(ny-2))
|
|
theta(ii) = (gozd+(ix+1)*dvzd)*pi/180
|
|
phi(ii) = pi/2-(goxd-(iy+1)*dvxd)*pi/180
|
|
rrad(ii) = radius-depz(iz+1)*hvratio
|
|
enddo
|
|
|
|
xpts = rrad*sin(phi)*cos(theta)
|
|
ypts = rrad*sin(phi)*sin(theta)
|
|
zpts = rrad*cos(phi)
|
|
|
|
idx = 0
|
|
do iz = 1,nz-1
|
|
do iy = 1,ny-2
|
|
do ix = 1,nx-2
|
|
xs = rrad(iz)*sin(pi/2-lat(ix))*cos(lon(iy))
|
|
ys = rrad(iz)*sin(pi/2-lat(ix))*sin(lon(iy))
|
|
zs = rrad(iz)*cos(pi/2-lat(ix))
|
|
dis = (xpts-xs)**2+(ypts-ys)**2+(zpts-zs)**2
|
|
idx = idx+1
|
|
col(idx) = (iz-1)*(nx-2)*(ny-2)+(iy-1)*(nx-2)+ix
|
|
row(idx) = minloc(dis,1)
|
|
enddo
|
|
enddo
|
|
enddo
|
|
rw_p = 1.0
|
|
leniw_p = 2*ndim+1
|
|
lenrw_p = ndim
|
|
iw_p(1) = ndim
|
|
iw_p(2:ndim+1) = row
|
|
iw_p(ndim+2:2*ndim+1) = col
|
|
|
|
allocate(grow(ndim),gcol(nd),subrow(ncells))
|
|
maxnar = int(0.6*nd*ncells)
|
|
allocate(iwgp(maxnar*2+1),colgp(maxnar),rwgp(maxnar))
|
|
|
|
nzid = 0
|
|
do ii = 1,nd
|
|
grow = 0
|
|
start = sum(nrow(1:ii-1))
|
|
do ix = 1,nrow(ii)
|
|
grow(colg(start+ix)) = rw(start+ix)
|
|
enddo
|
|
!gcol = 0
|
|
!gcol(ii) = 1.0
|
|
!call aprod(2,nd,ndim,grow,gcol,leniw,lenrw,iw,rw)
|
|
subrow = 0
|
|
call aprod(1,ncells,ndim,grow,subrow,leniw_p,lenrw_p,iw_p,rw_p)
|
|
do ix = 1,ncells
|
|
if(abs(subrow(ix))>ftol) then
|
|
nzid = nzid+1
|
|
rwgp(nzid) = subrow(ix)
|
|
iwgp(1+nzid) = ii
|
|
colgp(nzid) = ix
|
|
endif
|
|
enddo
|
|
enddo
|
|
leniwgp = nzid*2+1
|
|
lenrwgp = nzid
|
|
iwgp(1) = lenrwgp
|
|
iwgp(nzid+2:nzid*2+1) = colgp(1:nzid)
|
|
|
|
norm = 0
|
|
do ii=1,nzid
|
|
norm(iwgp(1+ii+nzid)) = norm(iwgp(1+ii+nzid))+rwgp(ii)**2
|
|
enddo
|
|
|
|
do ii =1,ncells
|
|
norm(ii) = sqrt(norm(ii)/nd+0.01)
|
|
enddo
|
|
|
|
do ii =1,nzid
|
|
rwgp(ii) = rwgp(ii)/norm(iwgp(1+ii+nzid))
|
|
enddo
|
|
|
|
conlim = 50
|
|
itnlim = 100
|
|
atol = 1e-3/((dvxd+dvzd)*111.19/2.0*0.1) !1e-2
|
|
btol = 1e-3/(dvxd*nx*111.19/3.0)!1e-3
|
|
istop = 0
|
|
anorm = 0.0
|
|
acond = 0.0
|
|
arnorm = 0.0
|
|
xnorm = 0.0
|
|
localSize = int(ncells/4)
|
|
!damp = dampvel
|
|
! using lsmr to solve for the projection coefficients
|
|
!print*, 'LSMR beginning ...'
|
|
|
|
nout = -1
|
|
!nout = 36
|
|
!open(nout,file='lsmrout_sub.txt')
|
|
|
|
call LSMR(nd, ncells, leniwgp, lenrwgp,iwgp,rwgp,dres,damp,&
|
|
atol, btol, conlim, itnlim, localSize,nout,&
|
|
xunknown, istop, itn, anorm, acond,rnorm, arnorm, xnorm)
|
|
!close(nout)
|
|
do ii = 1,ncells
|
|
xunknown(ii) = xunknown(ii)/norm(ii)
|
|
enddo
|
|
norm = (norm**2-0.01)*nd
|
|
do ii = 1,ncells
|
|
if (norm(ii)<0.01) then
|
|
call random_number(rx)
|
|
xunknown(ii) = xunknown(ii)+rx-0.5
|
|
endif
|
|
enddo
|
|
|
|
dv(1:ndim) = 0
|
|
call aprod(2,ncells,ndim,dv,xunknown,leniw_p,lenrw_p,iw_p,rw_p)
|
|
deallocate(grow,gcol,subrow)
|
|
deallocate(theta,phi,rrad,dws,norm)
|
|
deallocate(xpts,ypts,zpts,dis,xunknown)
|
|
deallocate(iw_p,rw_p,row,col)
|
|
deallocate(lat,lon,rad)
|
|
deallocate(iwgp,colgp,rwgp)
|
|
|
|
contains
|
|
subroutine random_index( idx, weights )
|
|
integer :: idx
|
|
real, intent(in) :: weights(:)
|
|
|
|
real x, wsum, prob
|
|
|
|
wsum = sum( weights )
|
|
|
|
call random_number( x )
|
|
|
|
prob = 0
|
|
do idx = 1, size( weights )
|
|
prob = prob + weights( idx ) / wsum !! 0 < prob < 1
|
|
if ( x <= prob ) exit
|
|
enddo
|
|
end subroutine random_index
|
|
|
|
|
|
end subroutine
|