added missing file
This commit is contained in:
parent
8c9273d684
commit
9fd9bf5f9c
287
src/reflections.f90
Normal file
287
src/reflections.f90
Normal file
@ -0,0 +1,287 @@
|
||||
module reflections
|
||||
implicit none
|
||||
private
|
||||
integer, parameter :: r8=selected_real_kind(15,300)
|
||||
real(r8), parameter :: tinyr8=tiny(1._r8)
|
||||
public :: reflect,inters_linewall,inside
|
||||
public :: linecone_coord,interssegm_coord,interssegm
|
||||
contains
|
||||
|
||||
subroutine reflect(ki,nsurf,ko)
|
||||
implicit none
|
||||
real(r8), intent(in), dimension(3) :: ki
|
||||
real(r8), intent(in), dimension(3) :: nsurf
|
||||
real(r8), intent(out), dimension(3) :: ko
|
||||
real(r8) :: twokn,norm2
|
||||
norm2 = dot_product(nsurf,nsurf)
|
||||
if (norm2>0.0_r8) then
|
||||
twokn = 2.0_r8*dot_product(ki,nsurf)/norm2
|
||||
ko=ki-twokn*nsurf
|
||||
else
|
||||
ko=ki
|
||||
end if
|
||||
end subroutine reflect
|
||||
|
||||
subroutine inters_linewall(xv,kv,rw,zw,nw,sint,normw)
|
||||
implicit none
|
||||
real(r8), intent(in), dimension(3) :: xv,kv
|
||||
integer, intent(in) :: nw
|
||||
real(r8), dimension(nw), intent(in) :: rw,zw
|
||||
real(r8), intent(out) :: sint
|
||||
real(r8), dimension(3), intent(out) :: normw
|
||||
integer :: i,j,ni,iint
|
||||
real(r8), dimension(2) :: si,ti
|
||||
real(r8) :: drw,dzw,xint,yint,rint,l,kxy
|
||||
real(r8) :: tol=sqrt(epsilon(1.0_r8))
|
||||
sint=huge(sint)
|
||||
iint=0
|
||||
normw=0.0_r8
|
||||
do i=1,nw-1
|
||||
!search intersections with i-th wall segment
|
||||
call linecone_coord(xv,kv,rw(i:i+1),zw(i:i+1),si,ti,ni)
|
||||
do while (ni>0 .and. si(1)<=tol)
|
||||
!remove solutions with s<=0
|
||||
ni = ni-1
|
||||
si(1) = si(2)
|
||||
ti(1) = ti(2)
|
||||
end do
|
||||
do j=1,ni
|
||||
if ((si(j)<sint .or. iint==0) .and. ti(j)>=0._r8 .and. ti(j)<=1._r8) then
|
||||
!check intersection is in r,z range and keep the closest
|
||||
sint = si(j)
|
||||
iint = i
|
||||
end if
|
||||
end do
|
||||
end do
|
||||
if (iint==0) return
|
||||
!calculate wall normal at intersection point
|
||||
drw = rw(iint+1)-rw(iint)
|
||||
dzw = zw(iint+1)-zw(iint)
|
||||
xint = xv(1) + sint*kv(1)
|
||||
yint = xv(2) + sint*kv(2)
|
||||
rint = sqrt(xint**2+yint**2)
|
||||
l = sqrt(drw**2+dzw**2)
|
||||
kxy = sqrt(kv(1)**2+kv(2)**2)
|
||||
normw(3) = -drw/l
|
||||
if (rint>0.0_r8) then
|
||||
normw(1) = xint/rint*dzw/l
|
||||
normw(2) = yint/rint*dzw/l
|
||||
else
|
||||
normw(1) = kv(1)/kxy*dzw/l
|
||||
normw(2) = kv(2)/kxy*dzw/l
|
||||
end if
|
||||
!reverse normal if k.n>0
|
||||
if (dot_product(normw,kv)>0.0_r8) normw=-normw
|
||||
end subroutine inters_linewall
|
||||
|
||||
subroutine linecone_coord(xv,kv,rs,zs,s,t,n)
|
||||
implicit none
|
||||
real(r8), intent(in), dimension(3) :: xv,kv
|
||||
real(r8), intent(in), dimension(2) :: rs,zs
|
||||
real(r8), dimension(2), intent(out) :: s,t
|
||||
integer, intent(out) :: n
|
||||
real(r8) :: x0,y0,z0,kx,ky,kz
|
||||
real(r8) :: dr,dz,r,a,bhalf,c,delta,tvertex,zvertex,srmin,rmin,zrmin
|
||||
x0=xv(1)
|
||||
y0=xv(2)
|
||||
z0=xv(3)
|
||||
kx=kv(1)
|
||||
ky=kv(2)
|
||||
kz=kv(3)
|
||||
dr = rs(2)-rs(1)
|
||||
dz = zs(2)-zs(1)
|
||||
s = 0
|
||||
t = 0
|
||||
if (abs(dz)<tinyr8) then
|
||||
!surface in horizontal plane
|
||||
if (abs(kz)<tinyr8 .or. abs(dr)<tinyr8) then
|
||||
n = 0
|
||||
else
|
||||
s(1) = (zs(1)-z0)/kz
|
||||
r = sqrt((x0+s(1)*kx)**2+(y0+s(1)*ky)**2)
|
||||
t(1) = (r-rs(1))/dr
|
||||
n = 1
|
||||
end if
|
||||
else
|
||||
a = (kx**2+ky**2) - (dr/dz*kz)**2
|
||||
bhalf = -dr/dz*kz*rs(1) + (kx*x0 + ky*y0) - (dr/dz)**2*kz*(z0-zs(1))
|
||||
c = (x0**2+y0**2) - (rs(1) + dr/dz*(z0-zs(1)))**2
|
||||
if (abs(a)<tinyr8) then
|
||||
!line parallel to cone generator
|
||||
if (abs(dr)<tinyr8) then
|
||||
!cylinder and vertical line
|
||||
n = 0
|
||||
else
|
||||
tvertex = -rs(1)/dr
|
||||
zvertex = zs(1) + tvertex*dz
|
||||
srmin = -(kx*x0 + ky*y0)/(kx**2+ky**2)
|
||||
rmin = sqrt((x0+srmin*kx)**2+(y0+srmin*ky)**2)
|
||||
zrmin = z0 + srmin*kz
|
||||
if (rmin<tinyr8 .and. abs(zrmin-zvertex)<tinyr8) then
|
||||
!line passing by cone vertex
|
||||
!s(1) = srmin
|
||||
!t(1) = tvertex
|
||||
!n = 1
|
||||
n = 0
|
||||
else
|
||||
s(1) = -0.5_r8*c/bhalf
|
||||
t(1) = (kz*s(1)+(z0-zs(1)))/dz
|
||||
n = 1
|
||||
end if
|
||||
end if
|
||||
else
|
||||
delta = bhalf**2 - a*c
|
||||
if (delta<0) then
|
||||
n = 0
|
||||
else
|
||||
s(1) = (-bhalf+sqrt(delta))/a
|
||||
s(2) = (-bhalf-sqrt(delta))/a
|
||||
call bubble(s,2)
|
||||
t(:) = (kz*s(:)+(z0-zs(1)))/dz
|
||||
n = 2
|
||||
end if
|
||||
end if
|
||||
end if
|
||||
end subroutine linecone_coord
|
||||
|
||||
subroutine interssegm_coord(xa,ya,xb,yb,s,t,ierr)
|
||||
implicit none
|
||||
real(r8), dimension(2), intent(in) :: xa,ya,xb,yb
|
||||
real(r8), intent(out) :: s,t
|
||||
integer, intent(out) :: ierr
|
||||
real(r8) :: crossprod,dxa,dya,dxb,dyb
|
||||
dxa = xa(2)-xa(1)
|
||||
dya = ya(2)-ya(1)
|
||||
dxb = xb(2)-xb(1)
|
||||
dyb = yb(2)-yb(1)
|
||||
crossprod = dxb*dya - dxa*dyb
|
||||
if (abs(crossprod)<tiny(crossprod)) then
|
||||
s = 0.0_r8
|
||||
t = 0.0_r8
|
||||
ierr = 1
|
||||
else
|
||||
s = (dyb*(xa(1)-xb(1)) - dxb*(ya(1)-yb(1)))/crossprod
|
||||
t = (dya*(xa(1)-xb(1)) - dxa*(ya(1)-yb(1)))/crossprod
|
||||
ierr = 0
|
||||
end if
|
||||
end subroutine interssegm_coord
|
||||
|
||||
function interssegm(xa,ya,xb,yb)
|
||||
implicit none
|
||||
real(r8), dimension(2), intent(in) :: xa,ya,xb,yb
|
||||
logical :: interssegm
|
||||
real(r8) :: s,t
|
||||
integer :: ierr
|
||||
interssegm = .false.
|
||||
call interssegm_coord(xa,ya,xb,yb,s,t,ierr)
|
||||
if (ierr==0 .and. s>=0._r8 .and. s<=1._r8 .and. &
|
||||
t>=0._r8 .and. t<=1._r8) interssegm = .true.
|
||||
end function interssegm
|
||||
|
||||
function inside(xc,yc,n,x,y)
|
||||
implicit none
|
||||
integer, intent(in) :: n
|
||||
real(r8), dimension(n), intent(in) :: xc,yc
|
||||
real(r8), intent(in) :: x,y
|
||||
logical :: inside
|
||||
integer, dimension(n) :: jint
|
||||
real(r8), dimension(n) :: xint
|
||||
real(r8), dimension(n+1) :: xclosed,yclosed
|
||||
integer :: i,nj
|
||||
xclosed(1:n)=xc(1:n)
|
||||
yclosed(1:n)=yc(1:n)
|
||||
xclosed(n+1)=xc(1)
|
||||
yclosed(n+1)=yc(1)
|
||||
call locate_unord(yclosed,n+1,y,jint,n,nj)
|
||||
inside=.false.
|
||||
if (nj==0) return
|
||||
do i=1,nj
|
||||
xint(i)=intlin(yclosed(jint(i)),xclosed(jint(i)), &
|
||||
yclosed(jint(i)+1),xclosed(jint(i)+1),y)
|
||||
end do
|
||||
call bubble(xint,nj)
|
||||
inside=(mod(locate(xint,nj,x),2)==1)
|
||||
end function inside
|
||||
|
||||
function intlin(x1,y1,x2,y2,x) result(y)
|
||||
!linear interpolation
|
||||
!must be x1 != x2
|
||||
implicit none
|
||||
real(r8),intent(in) :: x1,y1,x2,y2,x
|
||||
real(r8) :: y
|
||||
real(r8) :: a
|
||||
a=(x2-x)/(x2-x1)
|
||||
y=a*y1+(1._r8-a)*y2
|
||||
end function intlin
|
||||
|
||||
subroutine locate_unord(a,n,x,j,m,nj)
|
||||
implicit none
|
||||
integer, intent(in) :: n,m
|
||||
integer, intent(out) :: nj
|
||||
real(r8), dimension(n), intent(in) :: a
|
||||
real(r8), intent(in) :: x
|
||||
integer, dimension(m), intent(inout) :: j
|
||||
integer :: i
|
||||
nj=0
|
||||
do i=1,n-1
|
||||
if (x>a(i).neqv.x>a(i+1)) then
|
||||
nj=nj+1
|
||||
if (nj<=m) j(nj)=i
|
||||
end if
|
||||
end do
|
||||
end subroutine locate_unord
|
||||
|
||||
function locate(a,n,x) result(j)
|
||||
!Given an array a(n), and a value x, with a(n) monotonic, either
|
||||
!increasing or decreasing, returns a value j such that
|
||||
!a(j) < x <= a(j+1) for a increasing, and such that
|
||||
!a(j+1) < x <= a(j) for a decreasing.
|
||||
!j=0 or j=n indicate that x is out of range (Numerical Recipes)
|
||||
implicit none
|
||||
integer, intent(in) :: n
|
||||
real(r8), dimension(n), intent(in) :: a
|
||||
real(r8), intent(in) :: x
|
||||
integer :: j
|
||||
integer :: jl,ju,jm
|
||||
logical :: incr
|
||||
jl=0
|
||||
ju=n+1
|
||||
incr=a(n)>a(1)
|
||||
do while ((ju-jl)>1)
|
||||
jm=(ju+jl)/2
|
||||
if(incr.eqv.(x>a(jm))) then
|
||||
jl=jm
|
||||
else
|
||||
ju=jm
|
||||
endif
|
||||
end do
|
||||
j=jl
|
||||
end function locate
|
||||
|
||||
subroutine order(p,q)
|
||||
!returns p,q in ascending order
|
||||
implicit none
|
||||
real(r8), intent(inout) :: p,q
|
||||
real(r8) :: temp
|
||||
if (p>q) then
|
||||
temp=p
|
||||
p=q
|
||||
q=temp
|
||||
end if
|
||||
end subroutine order
|
||||
|
||||
subroutine bubble(a,n)
|
||||
!bubble sorting of array a
|
||||
implicit none
|
||||
integer, intent(in) :: n
|
||||
real(r8), dimension(n), intent(inout) :: a
|
||||
integer :: i, j
|
||||
do i=1,n
|
||||
do j=n,i+1,-1
|
||||
call order(a(j-1), a(j))
|
||||
end do
|
||||
end do
|
||||
end subroutine bubble
|
||||
|
||||
end module reflections
|
||||
|
Loading…
Reference in New Issue
Block a user