Вычислить площадь поверхности и нормаль для каждой грани произвольного шестигранника - PullRequest
0 голосов
/ 13 сентября 2018

Я пытаюсь выяснить площадь поверхности каждой из граней куба и соответствующих внешних единичных нормалей.Эта операция выполняется на сетке конечных элементов, поэтому я преобразовал каждую поверхность куба в изопараметрическую форму, используя функции формы (базиса), а затем попытался извлечь площадь и нормали.

Вот код:

program polyhedron

IMPLICIT NONE

real(8)  coord(3,8)
INTEGER  face, INPT, I, ino,k, ii  
REAL(8)  XI(3), dNdxi(8,3), ZERO, ONE, MONE, EIGHT
REAL(8) VJACOB(3,3),XII(8,3),norm(3), TWO, THREE, FOUR, HALF, SIX
PARAMETER(ZERO=0.D0,ONE=1.D0,MONE=-1.D0,EIGHT=8.D0)
PARAMETER(TWO=2.D0,THREE=3.D0,FOUR=4.D0,HALF=0.5D0,SIX=6.D0)
REAL(8) dXdXi,dXdEta,dXdZeta,dYdXi,dYdEta,dYdZeta,dZdXi,dZdEta,area_isd
REAL(8) dZdZeta, dA, mag, normal(3,1),xLocal(4),yLocal(4),zLocal(4)


!COORDINATES OF THE CUBE

 coord(1,1)=1.00
 coord(2,1)=1.00
 coord(3,1)=1.00
 coord(1,2)=1.00
 coord(2,2)=0.00
 coord(3,2)=1.00
 coord(1,3)=1.00
 coord(2,3)=1.00
 coord(3,3)=0.00
 coord(1,4)=1.00
 coord(2,4)=0.00
 coord(3,4)=0.00
 coord(1,5)=0.00
 coord(2,5)=1.00
 coord(3,5)=1.00
 coord(1,6)=0.00
 coord(2,6)=0.00
 coord(3,6)=1.00
 coord(1,7)=0.00
 coord(2,7)=1.00
 coord(3,7)=0.00
 coord(1,8)=0.00
 coord(2,8)=0.00
 coord(3,8)=0.00

do face=1,6   !Loop over the faces
area_isd=0.0
call xintSurf3D4pt(face,xLocal,yLocal,zLocal) !get local points
do ii=1,4
call computeSurf3D(xLocal(ii),yLocal(ii),zLocal(ii),face,coord,dA,norm) !compute area and normal
area_isd=area_isd+dA
end do
write(*,*) 'face', face, 'area', area_isd
write(*,*) 'norm', norm
end do
end program polyhedron

Подпрограмма для вычисления локального якобиана и нормалей:

subroutine computeSurf3D(xLocal,yLocal,zLocal,face,coords,dA,normal)



IMPLICIT NONE

integer face,stat,i,j,k

real(8) xLocal,yLocal,zLocal,dA,dshxi(8,3),zero,dsh(8,3),one
real(8) coords(3,8),two,eighth,mapJ(3,3),mag,normal(3)

real(8) dXdXi,dXdEta,dXdZeta,dYdXi,dYdEta,dYdZeta,dZdXi,dZdEta
real(8) dZdZeta

parameter(one=1.d0,two=2.d0,eighth=1.d0/8.d0,zero=0.d0)

!Hex shape function derivatives  
dshxi(1,1) = -eighth*(one - yLocal)*(one - zLocal)
dshxi(1,2) = -eighth*(one - xLocal)*(one - zLocal)
dshxi(1,3) = -eighth*(one - xLocal)*(one - yLocal)
dshxi(2,1) = eighth*(one - yLocal)*(one - zLocal)
dshxi(2,2) = -eighth*(one + xLocal)*(one - zLocal)
dshxi(2,3) = -eighth*(one + xLocal)*(one - yLocal)
dshxi(3,1) = eighth*(one + yLocal)*(one - zLocal)
dshxi(3,2) = eighth*(one + xLocal)*(one - zLocal)
dshxi(3,3) = -eighth*(one + xLocal)*(one + yLocal)
dshxi(4,1) = -eighth*(one + yLocal)*(one - zLocal)
dshxi(4,2) = eighth*(one - xLocal)*(one - zLocal)
dshxi(4,3) = -eighth*(one - xLocal)*(one + yLocal)
dshxi(5,1) = -eighth*(one - yLocal)*(one + zLocal)
dshxi(5,2) = -eighth*(one - xLocal)*(one + zLocal)
dshxi(5,3) = eighth*(one - xLocal)*(one - yLocal)
dshxi(6,1) = eighth*(one - yLocal)*(one + zLocal)
dshxi(6,2) = -eighth*(one + xLocal)*(one + zLocal)
dshxi(6,3) = eighth*(one + xLocal)*(one - yLocal)
dshxi(7,1) = eighth*(one + yLocal)*(one + zLocal)
dshxi(7,2) = eighth*(one + xLocal)*(one + zLocal)
dshxi(7,3) = eighth*(one + xLocal)*(one + yLocal)
dshxi(8,1) = -eighth*(one + yLocal)*(one + zLocal)
dshxi(8,2) = eighth*(one - xLocal)*(one + zLocal)
dshxi(8,3) = eighth*(one - xLocal)*(one + yLocal)


      dXdXi = zero
      dXdEta = zero
      dXdZeta = zero
      dYdXi = zero
      dYdEta = zero
      dYdZeta = zero
      dZdXi = zero
      dZdEta = zero
      dZdZeta = zero
      do k=1,8
         dXdXi = dXdXi + dshxi(k,1)*coords(1,k)
         dXdEta = dXdEta + dshxi(k,2)*coords(1,k)
         dXdZeta = dXdZeta + dshxi(k,3)*coords(1,k)
         dYdXi = dYdXi + dshxi(k,1)*coords(2,k)
         dYdEta = dYdEta + dshxi(k,2)*coords(2,k)
         dYdZeta = dYdZeta + dshxi(k,3)*coords(2,k)
         dZdXi = dZdXi + dshxi(k,1)*coords(3,k)
         dZdEta = dZdEta + dshxi(k,2)*coords(3,k)
         dZdZeta = dZdZeta + dshxi(k,3)*coords(3,k)
      enddo


      ! Jacobian of the mapping
      !
      if((face.eq.1).or.(face.eq.2)) then
         ! zeta = constant on this face
         dA = dsqrt((dYdXi*dZdEta - dYdEta*dZdXi)**2+(dXdXi*dZdEta - dXdEta*dZdXi)**2+(dXdXi*dYdEta - dXdEta*dYdXi)**2)
      elseif((face.eq.3).or.(face.eq.4)) then
         ! eta = constant on this face
         dA = dsqrt((dYdXi*dZdZeta - dYdZeta*dZdXi)**2+(dXdXi*dZdZeta - dXdZeta*dZdXi)**2+(dXdXi*dYdZeta - dXdZeta*dYdXi)**2)
      elseif((face.eq.5).or.(face.eq.6)) then
         ! xi = constant on this face
         dA = dsqrt((dYdEta*dZdZeta - dYdZeta*dZdEta)**2+(dXdEta*dZdZeta - dXdZeta*dZdEta)**2+(dXdEta*dYdZeta - dXdZeta*dYdEta)**2)
      endif



      !
      if((face.eq.1).or.(face.eq.2)) then
         ! zeta = constant on this face
         normal(1) = dYdXi*dZdEta - dYdEta*dZdXi
         normal(2) = dXdXi*dZdEta - dXdEta*dZdXi
         normal(3) = dXdXi*dYdEta - dXdEta*dYdXi
         if(face.eq.1) normal = -normal
      elseif((face.eq.3).or.(face.eq.4)) then
         ! eta = constant on this face
         normal(1) = dYdXi*dZdZeta - dYdZeta*dZdXi
         normal(2) = dXdXi*dZdZeta - dXdZeta*dZdXi
         normal(3) = dXdXi*dYdZeta - dXdZeta*dYdXi
         if(face.eq.3) normal = -normal
      elseif((face.eq.5).or.(face.eq.6)) then
         ! xi = constant on this face
         normal(1) = dYdEta*dZdZeta - dYdZeta*dZdEta
         normal(2) = dXdEta*dZdZeta - dXdZeta*dZdEta
         normal(3) = dXdEta*dYdZeta - dXdZeta*dYdEta
         if(face.eq.5) normal = -normal
      endif
      mag = dsqrt(normal(1)**two+normal(2)**two+normal(3)**two)
      normal(1) = normal(1)/mag
      normal(2) = normal(2)/mag
      normal(3) = normal(3)/mag


end subroutine computeSurf3D

Локальные точки Гаусса получены из этой подпрограммы:

subroutine xintSurf3D4pt(face,xLocal,yLocal,zLocal)



      implicit none

integer face
real(8) xLocal(4),yLocal(4),zLocal(4),w(4),one,three
parameter(one=1.d0,three=3.d0)




      ! Gauss pt locations in master element
      !
      if(face.eq.1) then
         xLocal(1) = -dsqrt(one/three)
         yLocal(1) = -dsqrt(one/three)
         zLocal(1) = -one
         xLocal(2) = dsqrt(one/three)
         yLocal(2) = -dsqrt(one/three)
         zLocal(2) = -one
         xLocal(3) = dsqrt(one/three)
         yLocal(3) = dsqrt(one/three)
         zLocal(3) = -one
         xLocal(4) = -dsqrt(one/three)
         yLocal(4) = dsqrt(one/three)
         zLocal(4) = -one
      elseif(face.eq.2) then
         xLocal(1) = -dsqrt(one/three)
         yLocal(1) = -dsqrt(one/three)
         zLocal(1) = one
         xLocal(2) = dsqrt(one/three)
         yLocal(2) = -dsqrt(one/three)
         zLocal(2) = one
         xLocal(3) = dsqrt(one/three)
         yLocal(3) = dsqrt(one/three)
         zLocal(3) = one
         xLocal(4) = -dsqrt(one/three)
         yLocal(4) = dsqrt(one/three)
         zLocal(4) = one
      elseif(face.eq.3) then
         xLocal(1) = -dsqrt(one/three)
         yLocal(1) = -one
         zLocal(1) = -dsqrt(one/three)
         xLocal(2) = dsqrt(one/three)
         yLocal(2) = -one
         zLocal(2) = -dsqrt(one/three)
         xLocal(3) = dsqrt(one/three)
         yLocal(3) = -one
         zLocal(3) = dsqrt(one/three)
         xLocal(4) = -dsqrt(one/three)
         yLocal(4) = -one
         zLocal(4) = dsqrt(one/three)
      elseif(face.eq.4) then
         xLocal(1) = one
         yLocal(1) = -dsqrt(one/three)
         zLocal(1) = -dsqrt(one/three)
         xLocal(2) = one
         yLocal(2) = dsqrt(one/three)
         zLocal(2) = -dsqrt(one/three)
         xLocal(3) = one
         yLocal(3) = dsqrt(one/three)
         zLocal(3) = dsqrt(one/three)
         xLocal(4) = one
         yLocal(4) = -dsqrt(one/three)
         zLocal(4) = dsqrt(one/three)
      elseif(face.eq.5) then
         xLocal(1) = -dsqrt(one/three)
         yLocal(1) = one
         zLocal(1) = -dsqrt(one/three)
         xLocal(2) = dsqrt(one/three)
         yLocal(2) = one
         zLocal(2) = -dsqrt(one/three)
         xLocal(3) = dsqrt(one/three)
         yLocal(3) = one
         zLocal(3) = dsqrt(one/three)
         xLocal(4) = -dsqrt(one/three)
         yLocal(4) = one
         zLocal(4) = dsqrt(one/three)
      elseif(face.eq.6) then
         xLocal(1) = -one
         yLocal(1) = -dsqrt(one/three)
         zLocal(1) = -dsqrt(one/three)
         xLocal(2) = -one
         yLocal(2) = dsqrt(one/three)
         zLocal(2) = -dsqrt(one/three)
         xLocal(3) = -one
         yLocal(3) = dsqrt(one/three)
         zLocal(3) = dsqrt(one/three)
         xLocal(4) = -one
         yLocal(4) = -dsqrt(one/three)
         zLocal(4) = dsqrt(one/three)
      endif

      end subroutine xintSurf3D4pt

Площадь каждой поверхности должна составлять 1 единицу, в данном случае, но этот код так не возвращается.Нормы тоже неверные.Вывод

    face           1 area  0.57735026918962573     
 norm   1.0000000000000000        0.0000000000000000E+000   0.0000000000000000E+000
 face           2 area  0.57735026918962573     
 norm  -1.0000000000000000       -0.0000000000000000E+000  -0.0000000000000000E+000
 face           3 area   1.0000000000000000     
 norm   0.0000000000000000E+000  -0.0000000000000000E+000   1.0000000000000000     
 face           4 area  0.57735026918962573     
 norm  -0.0000000000000000E+000   0.0000000000000000E+000  -1.0000000000000000     
 face           5 area   1.1547005383792515     
 norm  -0.0000000000000000E+000  0.86602540378443871       0.50000000000000000     
 face           6 area   1.4142135623730951     
 norm   0.0000000000000000E+000 -0.70710678118654746      -0.70710678118654746 

Примечание: а.Это не всегда куб, это может быть любой неправильный шестигранник, поэтому области не всегда будут равны, поэтому нам нужно вычислить каждый из них.б.Грани могут быть ориентированы в разных направлениях, поэтому изопараметрическое преобразование является своего рода необходимым.

Это правильный способ решения этой проблемы?Буду рад, если кто-нибудь поможет мне разобраться в этом.Я также пытался использовать векторное произведение диагоналей для каждой из граней, чтобы вычислить площадь и единицу нормалей, но они не работают, когда структура нерегулярна.Вот пример изображения неправильного шестигранника 1 .Обычный рубин примерно куб выглядит примерно так. 2

1 Ответ

0 голосов
/ 14 сентября 2018

Нормальный: возьмите три вершины и вычислите перекрестное произведение векторов, которые они образуют.

Площадь: примените формулу шнурка для XY, YZ и ZX, затем возьмите евклидову норму трех результатов.

...