Files
LaGriT/src/dihangle_element.f
2025-12-17 11:00:57 +08:00

169 lines
5.7 KiB
Fortran
Executable File

*deck dihangle_element
subroutine dihangle_element(ielmtyp,xice,yice,zice,
* minangle,maxangle)
C
C
C #####################################################################
C
C PURPOSE -
C
C Finds the max and min dihedral angles between adjacent
C faces of a 3D element or edges of a 2D element.
C
C INPUT ARGUMENTS -
C
C ielmtyp : Element type.
C (xice(),yice(),zice()) : The coordinates of the points of the
C element. They must be in the order
C in which they appear in itet.
C
C OUTPUT ARGUMENTS -
C
C minangle,maxangle : The min and max angles of the element
C in radians.
C
C CHANGE HISTORY -
C
C $Log: dihangle_element.f,v $
C Revision 2.00 2007/11/05 19:45:52 spchu
C Import to CVS
C
CPVCS
CPVCS Rev 1.0 Fri Aug 29 14:06:56 1997 dcg
CPVCS Initial revision.
C
C ######################################################################
C
C
implicit none
C
include "local_element.h"
C
character* 132 logmess
integer icscode
integer ielmtyp
real*8 xice(1000000),yice(1000000),zice(1000000)
real*8 minangle,maxangle
real*8 f_angle
integer i,j,k,l,ptcount,pointsi,pointsj,k1,l1,k2,l2
real*8 x1,y1,z1,x2,y2,z2,dot,norm1,norm2
real*8 xici(8),yici(8),zici(8),xicj(8),yicj(8),zicj(8)
C
C ######################################################################
C
C
minangle = 8.0
maxangle = -8.0
if ((ielmtyp .eq. ifelmtet) .or.
* (ielmtyp .eq. ifelmpyr) .or.
* (ielmtyp .eq. ifelmpri) .or.
* (ielmtyp .eq. ifelmhex) .or.
* (ielmtyp .eq. ifelmhyb)) then
do i=1,nelmnef(ielmtyp)-1
do j=i+1,nelmnef(ielmtyp)
ptcount = 0
do k=1,ielmface0(i,ielmtyp)
k1 = ielmface1(k,i,ielmtyp)
do l=1,ielmface0(j,ielmtyp)
C Check to see how many points these faces meet in
l1 = ielmface1(l,j,ielmtyp)
if (k1 .eq. l1) then
ptcount = ptcount + 1
endif
enddo
C Record the coordinates of the point k on face i
xici(k)=xice(k1)
yici(k)=yice(k1)
zici(k)=zice(k1)
enddo
pointsi = ielmface0(i,ielmtyp)
C Record the coordinates of all points on face j
C Didn't do it above to avoid doing it multiple times
do l=1,ielmface0(j,ielmtyp)
l1 = ielmface1(l,j,ielmtyp)
xicj(l)=xice(l1)
yicj(l)=yice(l1)
zicj(l)=zice(l1)
enddo
pointsj = ielmface0(j,ielmtyp)
if (ptcount .ge. 2) then
call dihangle_face(pointsi,xici,yici,zici,
* pointsj,xicj,yicj,zicj,f_angle)
if (f_angle .lt. minangle) then
minangle = f_angle
endif
if (f_angle .gt. maxangle) then
maxangle = f_angle
endif
endif
if (ptcount .gt. 2) then
write (logmess,"('Too many face-to-face ',
* 'intersections.')")
call writloga('default',0,logmess,0,icscode)
return
endif
enddo
enddo
elseif ((ielmtyp .eq. ifelmtri) .or.
* (ielmtyp .eq. ifelmqud)) then
do i=1,nelmnee(ielmtyp)-1
do j=i+1,nelmnee(ielmtyp)
ptcount = 0
do k=1,2
k1 = ielmedge1(k,i,ielmtyp)
do l=1,2
C Check to see if these edges meet
l1 = ielmedge1(l,j,ielmtyp)
if (k1 .eq. l1) then
ptcount = ptcount + 1
C Get the other point on each edge
k2 = ielmedge1(3-k,i,ielmtyp)
l2 = ielmedge1(3-l,j,ielmtyp)
x1 = xice(k2) - xice(k1)
y1 = yice(k2) - yice(k1)
z1 = zice(k2) - zice(k1)
x2 = xice(l2) - xice(l1)
y2 = yice(l2) - yice(l1)
z2 = zice(l2) - zice(l1)
norm1 = sqrt(x1*x1 + y1*y1 + z1*z1)
norm2 = sqrt(x2*x2 + y2*y2 + z2*z2)
x1 = x1 / norm1
y1 = y1 / norm1
z1 = z1 / norm1
x2 = x2 / norm2
y2 = y2 / norm2
z2 = z2 / norm2
dot = x1*x2 + y1*y2 + z1*z2
f_angle = acos(dot)
if (f_angle .lt. minangle) then
minangle = f_angle
endif
if (f_angle .gt. maxangle) then
maxangle = f_angle
endif
endif
enddo
enddo
if (ptcount .gt. 1) then
write (logmess,"('Too many edge-to-edge ',
* 'intersections.')")
call writloga('default',0,logmess,0,icscode)
return
endif
enddo
enddo
else
write (logmess,"('Only triangles, quads and 3D elements ',
* 'may have their angles computed.')")
call writloga('default',0,logmess,0,icscode)
return
endif
return
end