DSurfTomo/src/voronoiproj.f90

223 lines
5.9 KiB
Fortran
Raw Normal View History

2020-04-20 01:36:13 +08:00
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
2020-04-20 01:36:13 +08:00
! integer iw(leniw)
2020-07-09 08:51:56 +08:00
integer colg(lenrw),nrow(nd)
real depz(nz)
real rw(lenrw)
2020-07-09 08:51:56 +08:00
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
2020-07-09 08:51:56 +08:00
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
2020-04-20 01:36:13 +08:00
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
2020-07-09 08:51:56 +08:00
allocate(theta(ncells),phi(ncells),rrad(ncells),norm(ncells))
allocate(xpts(ncells),ypts(ncells),zpts(ncells),dis(ncells),xunknown(ncells))
allocate(rw_p(ndim))
2020-07-09 08:51:56 +08:00
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
2020-07-09 08:51:56 +08:00
! 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
2020-04-20 01:36:13 +08:00
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
2020-04-19 19:52:07 +08:00
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 ...'
2020-04-21 18:54:49 +08:00
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)
2020-04-21 18:54:49 +08:00
!close(nout)
do ii = 1,ncells
xunknown(ii) = xunknown(ii)/norm(ii)
enddo
2020-07-09 08:51:56 +08:00
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)
2020-07-09 08:51:56 +08:00
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