-
Douglas Guptill authoredDouglas Guptill authored
check_delaunay.f90 13.01 KiB
!------------------------------------------------------------------------------|
!------------------------------------------------------------------------------|
! |
! ||===\\ |
! || \\ |
! || || //==\\ || || //==|| ||/==\\ |
! || || || || || || || || || || |
! || // || || || || || || || |
! ||===// \\==// \\==\\ \\==\\ || |
! |
!------------------------------------------------------------------------------|
!------------------------------------------------------------------------------|
! |
! CHECK_DELAUNAY Apr. 2008 |
! |
!------------------------------------------------------------------------------|
!------------------------------------------------------------------------------|
subroutine check_delaunay (params,surface,is,istep,string,ref_count)
use definitions
use constants
!------------------------------------------------------------------------------|
!(((((((((((((((( Purpose of the routine ))))))))))))))))))))))))))))))))))))))
!------------------------------------------------------------------------------|
! This routine builds an edge array between a set of particles on a surface.
! It uses the delaunay triangulation and then steps through the triangles
! to build the edge information.
! ed is the computed edge array
! nedge is the number of edges
! nedgepernode,nodenodenumber and nodenodenumber contain the list of edges
! that start from each node; for a given node i
! their number is nedgepernode(i), the edge number in the list of edges is
! nodeedgenumber(j,i) and the node at the end of the edge is
! nodenodenumber(j,i) for j=1,nedgepernode(i)
! this subroutine then updates the Delaunay triangulation around a set of points
! located on a surface in three dimensional space. A non Euclidian metrics is
! used that takes into account the divergence of normals attached to the points
! such that folding over of the surface is impossible
! The Delaunay triangumation is UPDATED, not reconstructed at each time step.
! First the delaunay triangulation is checked along each edge between two
! adjacent triangles using a generalized in-circle test based on the calculation
! of distances only; the test is based on an angle.
! where the test is positive, edge flipping takes place and all the arrays are
! permutated (icon, edge, and subsidiary arrays )
!------------------------------------------------------------------------------|
!(((((((((((((((( declaration of the subroutine arguments ))))))))))))))))))))
!------------------------------------------------------------------------------|
implicit none
type (parameters) params
type (sheet) surface
integer is
integer istep
character*(*) string
integer ref_count
!------------------------------------------------------------------------------|
!(((((((((((((((( declaration of the subroutine internal variables )))))))))))))
!------------------------------------------------------------------------------|
integer nsurfacen
integer ntriangle
integer nedge
integer iedge,jedge
integer nnmax,nflip,counter
integer ie,inode,kp,kpp
integer inodep,inodepp
integer iproc,nproc,ierr
integer i1,i2,j1,j2,k,k12,k21,n1,n2,t1,t2,nn,j,jj,err
integer,dimension(:) ,allocatable :: nedgepernode
integer,dimension(:,:),allocatable :: nodenodenumber,nodeedgenumber
logical,dimension(:) ,allocatable :: icheck,icheckp
type (edge), dimension(:), allocatable :: ed
double precision dn1n2,dn1m1,dn1m2,dn2m1,dn2m2,dist1,dist2
double precision, external :: dist
character*72 :: shift
!------------------------------------------------------------------------------|
!------------------------------------------------------------------------------|
INCLUDE 'mpif.h'
call mpi_comm_size (mpi_comm_world,nproc,ierr)
call mpi_comm_rank (mpi_comm_world,iproc,ierr)
shift=' '
!------------------------
! build edge information
!------------------------
nsurfacen=surface%nsurface
ntriangle=surface%nt
nedge=nsurfacen+ntriangle-1
nnmax=12 ! nnmax is maximum number of neighbours in triangulation (should be around 6 on average)
allocate (ed(nedge),stat=err)
allocate (nedgepernode(nsurfacen),stat=err)
allocate (nodenodenumber(nnmax,nsurfacen),stat=err)
allocate (nodeedgenumber(nnmax,nsurfacen),stat=err)
ed%t1=0
ed%t2=0
nedgepernode=0
iedge=0
do ie=1,ntriangle
do k=1,3
inode=surface%icon(k,ie)
kp=mod(k,3)+1
kpp=mod(k+1,3)+1
inodep=surface%icon(kp,ie)
inodepp=surface%icon(kpp,ie)
do j=1,nedgepernode(inodep)
if (nodenodenumber(j,inodep).eq.inode) then
jedge=nodeedgenumber(j,inodep)
ed(jedge)%m2=inodepp
ed(jedge)%t2=ie
goto 111
endif
enddo
iedge=iedge+1
if (iedge.gt.nedge) call stop_run ('too many edges in delaunay2$')
nedgepernode(inode)=nedgepernode(inode)+1
if (nedgepernode(inode).gt.nnmax) then
if (iproc.eq.0) write (8,*) 'node',inode,'has',nedgepernode(inode),'neighbours'
call stop_run ('too many neighbours$')
endif
nodenodenumber(nedgepernode(inode),inode)=inodep
nodeedgenumber(nedgepernode(inode),inode)=iedge
ed(iedge)%n1=inode
ed(iedge)%n2=inodep
ed(iedge)%m1=inodepp
ed(iedge)%t1=ie
111 continue
enddo
enddo
if (iedge/=nedge) then
if (iproc.eq.0) write (8,*) 'iedge=',iedge,'nedge=',nedge
call stop_run ('pb_b in check_delaunay$')
endif
!--------------------------------------------------
! check state of triangulation with in-circle test
!--------------------------------------------------
allocate (icheck(nedge),stat=err)
allocate (icheckp(nedge),stat=err)
nflip=1
counter=0
do while (nflip > 0)
counter=counter+1
icheck=.false.
icheckp=.false.
do iedge=1+iproc,nedge,nproc
if ((ed(iedge)%t1.gt.0) .and. (ed(iedge)%t2.gt.0)) then
i1=ed(iedge)%n1
i2=ed(iedge)%n2
j1=ed(iedge)%m1
j2=ed(iedge)%m2
dn1n2=dist(surface%x (i1),surface%x (i2),surface%y (i1),surface%y (i2),surface%z (i1),surface%z (i2), &
surface%xn(i1),surface%xn(i2),surface%yn(i1),surface%yn(i2),surface%zn(i1),surface%zn(i2), &
params%distance_exponent)
dn1m1=dist(surface%x (i1),surface%x (j1),surface%y (i1),surface%y (j1),surface%z (i1),surface%z (j1), &
surface%xn(i1),surface%xn(j1),surface%yn(i1),surface%yn(j1),surface%zn(i1),surface%zn(j1), &
params%distance_exponent)
dn1m2=dist(surface%x (i1),surface%x (j2),surface%y (i1),surface%y (j2),surface%z (i1),surface%z (j2), &
surface%xn(i1),surface%xn(j2),surface%yn(i1),surface%yn(j2),surface%zn(i1),surface%zn(j2), &
params%distance_exponent)
dn2m1=dist(surface%x (i2),surface%x (j1),surface%y (i2),surface%y (j1),surface%z (i2),surface%z (j1), &
surface%xn(i2),surface%xn(j1),surface%yn(i2),surface%yn(j1),surface%zn(i2),surface%zn(j1), &
params%distance_exponent)
dn2m2=dist(surface%x (i2),surface%x (j2),surface%y (i2),surface%y (j2),surface%z (i2),surface%z (j2), &
surface%xn(i2),surface%xn(j2),surface%yn(i2),surface%yn(j2),surface%zn(i2),surface%zn(j2), &
params%distance_exponent)
dist1=(dn1m1**2+dn2m1**2-dn1n2**2)/(2.d0*dn1m1*dn2m1)
dist2=(dn1m2**2+dn2m2**2-dn1n2**2)/(2.d0*dn1m2*dn2m2)
dist1=acos(dist1)
dist2=acos(dist2)
icheckp(iedge) = (dist1+dist2.gt.pi) ! incircle test
endif
enddo
call mpi_allreduce (icheckp,icheck,nedge,mpi_logical,mpi_lor,mpi_comm_world,ierr)
nflip = count(icheck)
if (iproc.eq.0 .and. params%debug>=1) write(*,'(a,i2,a,i5,a)') shift//'S.',is,':', nflip,' flips in delaunay2'
do iedge=1,nedge
if (icheck(iedge)) then
!--------------------------------------------------------
! finds where n2 is in icon(:,t1) and n1 is in icon(:,t2)
!--------------------------------------------------------
do k=1,3
if (surface%icon(k,ed(iedge)%t1).eq.ed(iedge)%n2) k12=k
if (surface%icon(k,ed(iedge)%t2).eq.ed(iedge)%n1) k21=k
enddo
!--------------------------------------------------------
! permutates nodal info in edge
!--------------------------------------------------------
n1=ed(iedge)%n1
n2=ed(iedge)%n2
ed(iedge)%n1=ed(iedge)%m2
ed(iedge)%n2=ed(iedge)%m1
ed(iedge)%m1=n1
ed(iedge)%m2=n2
!--------------------------------------------------------
! permutates nodal info in icon
!--------------------------------------------------------
t1=ed(iedge)%t1
t2=ed(iedge)%t2
surface%icon(k12,t1)=ed(iedge)%n1
surface%icon(k21,t2)=ed(iedge)%n2
!--------------------------------------------------------
! updates info in nedgepernode, nodenodenumber and nodeedgenumber
!--------------------------------------------------------
nn=ed(iedge)%m1
do j=1,nedgepernode(nn)
if (nodeedgenumber(j,nn).eq.iedge) then
do jj=j+1,nedgepernode(nn)
nodenodenumber(jj-1,nn)=nodenodenumber(jj,nn)
nodeedgenumber(jj-1,nn)=nodeedgenumber(jj,nn)
enddo
endif
enddo
nedgepernode(nn)=nedgepernode(nn)-1
nn=ed(iedge)%n1
nedgepernode(nn)=nedgepernode(nn)+1
nodenodenumber(nedgepernode(nn),nn)=ed(iedge)%n2
nodeedgenumber(nedgepernode(nn),nn)=iedge
!--------------------------------------------------------
! updates triangle info in adjacent edges
!--------------------------------------------------------
nn=ed(iedge)%n1
do j=1,nedgepernode(nn)
if (nodenodenumber(j,nn).eq.ed(iedge)%m1) then
ed(nodeedgenumber(j,nn))%t2=ed(iedge)%t1
ed(nodeedgenumber(j,nn))%m2=ed(iedge)%n2
endif
enddo
nn=ed(iedge)%m1
do j=1,nedgepernode(nn)
if (nodenodenumber(j,nn).eq.ed(iedge)%n1) then
ed(nodeedgenumber(j,nn))%t1=ed(iedge)%t1
ed(nodeedgenumber(j,nn))%m1=ed(iedge)%n2
endif
enddo
nn=ed(iedge)%n2
do j=1,nedgepernode(nn)
if (nodenodenumber(j,nn).eq.ed(iedge)%m2) then
ed(nodeedgenumber(j,nn))%t2=ed(iedge)%t2
ed(nodeedgenumber(j,nn))%m2=ed(iedge)%n1
endif
enddo
nn=ed(iedge)%m2
do j=1,nedgepernode(nn)
if (nodenodenumber(j,nn).eq.ed(iedge)%n2) then
ed(nodeedgenumber(j,nn))%t1=ed(iedge)%t2
ed(nodeedgenumber(j,nn))%m1=ed(iedge)%n1
endif
enddo
nn=ed(iedge)%n1
do j=1,nedgepernode(nn)
if (nodenodenumber(j,nn).eq.ed(iedge)%m2) then
ed(nodeedgenumber(j,nn))%m1=ed(iedge)%n2
endif
enddo
nn=ed(iedge)%m1
do j=1,nedgepernode(nn)
if (nodenodenumber(j,nn).eq.ed(iedge)%n2) then
ed(nodeedgenumber(j,nn))%m2=ed(iedge)%n1
endif
enddo
nn=ed(iedge)%n2
do j=1,nedgepernode(nn)
if (nodenodenumber(j,nn).eq.ed(iedge)%m1) then
ed(nodeedgenumber(j,nn))%m1=ed(iedge)%n1
endif
enddo
nn=ed(iedge)%m2
do j=1,nedgepernode(nn)
if (nodenodenumber(j,nn).eq.ed(iedge)%n1) then
ed(nodeedgenumber(j,nn))%m2=ed(iedge)%n2
endif
enddo
endif
enddo
if (params%debug .ge.2) call output_surf(surface,is,string,istep,ref_count)
end do
deallocate (icheck)
deallocate (icheckp)
deallocate (ed)
deallocate (nedgepernode)
deallocate (nodenodenumber)
deallocate (nodeedgenumber)
end subroutine
!------------------------------------------------------------------------------|
!------------------------------------------------------------------------------|
function dist (x1,x2,y1,y2,z1,z2,xn1,xn2,yn1,yn2,zn1,zn2,distance_exponent)
implicit none
double precision dist
double precision x1,y1,z1,x2,y2,z2
double precision xn1,yn1,zn1,xn2,yn2,zn2
double precision distance_exponent
!prod=xxn(i1)*xxn(i2)+yyn(i1)*yyn(i2)+zzn(i1)*zzn(i2)
!dist=sqrt(x**2+y**2+z**2)/sqrt(prod)
!dist=sqrt(x**2+y**2+z**2)/prod
!dist=sqrt(x**2+y**2+z**2)/prod**distance_exponent
dist=sqrt((x2-x1)**2+(y2-y1)**2+(z2-z1)**2)
return
end
!------------------------------------------------------------------------------|
!------------------------------------------------------------------------------|