我有一个立方体,它通过平分每个边被分成 8 个小立方体,我试图找出每个面的表面积和它们对应的外法线。此操作是在有限元网格上完成的,因此我使用 shape(basis) 函数将立方体转换为等参数形式,然后尝试提取面积和法线。
这是代码的一部分:
program polyhedron
DO INPT=1,8 !LOOP OVER 8 SMALL CUBES
! GAUSS POINTS
XII(1,1) = MONE/THREE**HALF
XII(1,2) = MONE/THREE**HALF
XII(1,3) = MONE/THREE**HALF
XII(2,1) = ONE/THREE**HALF
XII(2,2) = MONE/THREE**HALF
XII(2,3) = MONE/THREE**HALF
XII(3,1) = ONE/THREE**HALF
XII(3,2) = ONE/THREE**HALF
XII(3,3) = MONE/THREE**HALF
XII(4,1) = MONE/THREE**HALF
XII(4,2) = ONE/THREE**HALF
XII(4,3) = MONE/THREE**HALF
XII(5,1) = MONE/THREE**HALF
XII(5,2) = MONE/THREE**HALF
XII(5,3) = ONE/THREE**HALF
XII(6,1) = ONE/THREE**HALF
XII(6,2) = MONE/THREE**HALF
XII(6,3) = ONE/THREE**HALF
XII(7,1) = ONE/THREE**HALF
XII(7,2) = ONE/THREE**HALF
XII(7,3) = ONE/THREE**HALF
XII(8,1) = MONE/THREE**HALF
XII(8,2) = ONE/THREE**HALF
XII(8,3) = ONE/THREE**HALF
XI(1) = XII(INPT,1)
XI(2) = XII(INPT,2)
XI(3) = XII(INPT,3)
DO I=1,8
DO J=1,3
dNdxi(I,J) = ZERO
END DO
END DO
!HEXAHEDRAL SHAPE FUNCTION DERIVATIVES
dNdxi(1,1) = MONE/EIGHT*(ONE-XI(2))*(ONE-XI(3))
dNdxi(1,2) = MONE/EIGHT*(ONE-XI(1))*(ONE-XI(3))
dNdxi(1,3) = MONE/EIGHT*(ONE-XI(1))*(ONE-XI(2))
dNdxi(2,1) = ONE/EIGHT*(ONE-XI(2))*(ONE-XI(3))
dNdxi(2,2) = MONE/EIGHT*(ONE+XI(1))*(ONE-XI(3))
dNdxi(2,3) = MONE/EIGHT*(ONE+XI(1))*(ONE-XI(2))
dNdxi(3,1) = ONE/EIGHT*(ONE+XI(2))*(ONE-XI(3))
dNdxi(3,2) = ONE/EIGHT*(ONE+XI(1))*(ONE-XI(3))
dNdxi(3,3) = MONE/EIGHT*(ONE+XI(1))*(ONE+XI(2))
dNdxi(4,1) = MONE/EIGHT*(ONE+XI(2))*(ONE-XI(3))
dNdxi(4,2) = ONE/EIGHT*(ONE-XI(1))*(ONE-XI(3))
dNdxi(4,3) = MONE/EIGHT*(ONE-XI(1))*(ONE+XI(2))
dNdxi(5,1) = MONE/EIGHT*(ONE-XI(2))*(ONE+XI(3))
dNdxi(5,2) = MONE/EIGHT*(ONE-XI(1))*(ONE+XI(3))
dNdxi(5,3) = ONE/EIGHT*(ONE-XI(1))*(ONE-XI(2))
dNdxi(6,1) = ONE/EIGHT*(ONE-XI(2))*(ONE+XI(3))
dNdxi(6,2) = MONE/EIGHT*(ONE+XI(1))*(ONE+XI(3))
dNdxi(6,3) = ONE/EIGHT*(ONE+XI(1))*(ONE-XI(2))
dNdxi(7,1) = ONE/EIGHT*(ONE+XI(2))*(ONE+XI(3))
dNdxi(7,2) = ONE/EIGHT*(ONE+XI(1))*(ONE+XI(3))
dNdxi(7,3) = ONE/EIGHT*(ONE+XI(1))*(ONE+XI(2))
dNdxi(8,1) = MONE/EIGHT*(ONE+XI(2))*(ONE+XI(3))
dNdxi(8,2) = ONE/EIGHT*(ONE-XI(1))*(ONE+XI(3))
dNdxi(8,3) = ONE/EIGHT*(ONE-XI(1))*(ONE+XI(2))
dXdXi = zero
dXdEta = zero
dXdZeta = zero
dYdXi = zero
dYdEta = zero
dYdZeta = zero
dZdXi = zero
dZdEta = zero
dZdZeta = zero
do k=1,8
dXdXi = dXdXi + dNdxi(k,1)*coords(1,k)
dXdEta = dXdEta + dNdxi(k,2)*coords(1,k)
dXdZeta = dXdZeta + dNdxi(k,3)*coords(1,k)
dYdXi = dYdXi + dNdxi(k,1)*coords(2,k)
dYdEta = dYdEta + dNdxi(k,2)*coords(2,k)
dYdZeta = dYdZeta + dNdxi(k,3)*coords(2,k)
dZdXi = dZdXi + dNdxi(k,1)*coords(3,k)
dZdEta = dZdEta + dNdxi(k,2)*coords(3,k)
dZdZeta = dZdZeta + dNdxi(k,3)*coords(3,k)
enddo
DO face=1,6 !LOOP OVER ALL 6 FACES OF THE SMALL CUBE
! Jacobian of the mapping
!
if((face.eq.1).or.(face.eq.2)) then
! zeta = constant on this face
dA = dsqrt((dYdXi*dZdEta - dYdEta*dZdXi)**two+ (dXdXi*dZdEta -&
&dXdEta*dZdXi)**two+ (dXdXi*dYdEta - dXdEta*dYdXi)**two)
elseif((face.eq.3).or.(face.eq.5)) then
! eta = constant on this face
dA = dsqrt((dYdXi*dZdZeta - dYdZeta*dZdXi)**two+ (dXdXi*dZdZeta -&
&dXdZeta*dZdXi)**two+ (dXdXi*dYdZeta - dXdZeta*dYdXi)**two)
elseif((face.eq.4).or.(face.eq.6)) then
! xi = constant on this face
dA = dsqrt((dYdEta*dZdZeta - dYdZeta*dZdEta)**two+ (dXdEta*dZdZeta -&
dXdZeta*dZdEta)**two+ (dXdEta*dYdZeta - dXdZeta*dYdEta)**two)
endif
write(*,*) 'face',face,'area is dA', dA
if((face.eq.1).or.(face.eq.2)) then
! zeta = constant on this face
normal(1,1) = dYdXi*dZdEta - dYdEta*dZdXi
normal(2,1) = dXdXi*dZdEta - dXdEta*dZdXi
normal(3,1) = 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,1) = dYdXi*dZdZeta - dYdZeta*dZdXi
normal(2,1) = dXdXi*dZdZeta - dXdZeta*dZdXi
normal(3,1) = 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,1) = dYdEta*dZdZeta - dYdZeta*dZdEta
normal(2,1) = dXdEta*dZdZeta - dXdZeta*dZdEta
normal(3,1) = dXdEta*dYdZeta - dXdZeta*dYdEta
if(face.eq.6) normal = -normal
endif
mag = dsqrt(normal(1,1)**two+normal(2,1)**two+normal(3,1)**two)
normal(1,1) = normal(1,1)/mag
normal(2,1) = normal(2,1)/mag
normal(3,1) = normal(3,1)/mag
write(*,*) 'face', face, 'normal is ',normal
END DO
每个小立方体的每个表面的面积应该是 0.25,在这种情况下,但这个代码没有返回。法线也没有正确定向,这里立方体与全局轴对齐,所以它应该是 1 或 -1。
注:一。这可能永远不是立方体,它可以是任何不规则的六面体,因此面积不会总是相等,因此我们需要计算它们中的每一个。湾。面可能沿着不同的方向定向,因此等参数变换是必要的。
此外,我已经使用每个面的向量来解决这个问题,而不使用等参数变换,我使用立方体的面的对角线并计算它们的叉积来找到面积和外部单位法线,当元素是时,该方法也会失败不规律。这部分代码如下所示:
IF (J==1) THEN
xsd1(1:4)=xsd(1:4)
ysd1(1:4)=ysd(1:4)
zsd1(1:4)=zsd(1:4)
b(1)=xsd1(1)-xsd1(3)
b(2)=ysd1(1)-ysd1(3)
b(3)=zsd1(1)-zsd1(3)
c(1)=xsd1(2)-xsd1(4)
c(2)=ysd1(2)-ysd1(4)
c(3)=zsd1(2)-zsd1(4)
call cross(c, b,crossproduct)
norm(:)=crossproduct/(crossproduct(1)**2+crossproduct(2)**2+crossproduct(3)**2)**0.5
area_isd=((crossproduct(1)**2+crossproduct(2)**2+crossproduct(3)**2)**0.5)/2
ELSE IF (J==2) THEN
xsd2(1:4)=xsd(5:8)
ysd2(1:4)=ysd(5:8)
zsd2(1:4)=zsd(5:8)
b(1)=xsd2(4)-xsd2(2)
b(2)=ysd2(4)-ysd2(2)
b(3)=zsd2(4)-zsd2(2)
c(1)=xsd2(3)-xsd2(1)
c(2)=ysd2(3)-ysd2(1)
c(3)=zsd2(3)-zsd2(1)
call cross(c, b,crossproduct)
norm(:)=crossproduct/(crossproduct(1)**2+crossproduct(2)**2+crossproduct(3)**2)**0.5
area_isd=((crossproduct(1)**2+crossproduct(2)**2+crossproduct(3)**2)**0.5)/2
ELSE IF (J==3) THEN
xsd3(1:2)=xsd(1:2)
xsd3(3)=xsd(6)
xsd3(4)=xsd(5)
ysd3(1:2)=ysd(1:2)
ysd3(3)=ysd(6)
ysd3(4)=ysd(5)
zsd3(1:2)=zsd(1:2)
zsd3(3)=zsd(6)
zsd3(4)=zsd(5)
b(1)=xsd3(4)-xsd3(2)
b(2)=ysd3(4)-ysd3(2)
b(3)=zsd3(4)-zsd3(2)
c(1)=xsd3(3)-xsd3(1)
c(2)=ysd3(3)-ysd3(1)
c(3)=zsd3(3)-zsd3(1)
call cross(c, b,crossproduct)
norm(:)=crossproduct/(crossproduct(1)**2+crossproduct(2)**2+crossproduct(3)**2)**0.5
area_isd=((crossproduct(1)**2+crossproduct(2)**2+crossproduct(3)**2)**0.5)/2
ELSE IF (J==4) THEN
xsd4(1:2)=xsd(7:8)
xsd4(3)=xsd(4)
xsd4(4)=xsd(3)
ysd4(1:2)=ysd(7:8)
ysd4(3)=ysd(4)
ysd4(4)=ysd(3)
zsd4(1:2)=zsd(7:8)
zsd4(3)=zsd(4)
zsd4(4)=zsd(3)
b(1)=xsd4(1)-xsd4(3)
b(2)=ysd4(1)-ysd4(3)
b(3)=zsd4(1)-zsd4(3)
c(1)=xsd4(2)-xsd4(4)
c(2)=ysd4(2)-ysd4(4)
c(3)=zsd4(2)-zsd4(4)
call cross(c, b,crossproduct)
norm(:)=crossproduct/(crossproduct(1)**2+crossproduct(2)**2+crossproduct(3)**2)**0.5
area_isd=((crossproduct(1)**2+crossproduct(2)**2+crossproduct(3)**2)**0.5)/2
ELSE IF (J==5) THEN
xsd5(1:2)=xsd(2:3)
xsd5(3)=xsd(7)
xsd5(4)=xsd(6)
ysd5(1:2)=ysd(2:3)
ysd5(3)=ysd(7)
ysd5(4)=ysd(6)
zsd5(1:2)=zsd(2:3)
zsd5(3)=zsd(7)
zsd5(4)=zsd(6)
b(1)=xsd5(4)-xsd5(2)
b(2)=ysd5(4)-ysd5(2)
b(3)=zsd5(4)-zsd5(2)
c(1)=xsd5(3)-xsd5(1)
c(2)=ysd5(3)-ysd5(1)
c(3)=zsd5(3)-zsd5(1)
call cross(c, b,crossproduct)
norm(:)=crossproduct/(crossproduct(1)**2+crossproduct(2)**2+crossproduct(3)**2)**0.5
area_isd=((crossproduct(1)**2+crossproduct(2)**2+crossproduct(3)**2)**0.5)/2
ELSE IF (J==6) THEN
xsd6(1)=xsd(1)
xsd6(2)=xsd(4)
xsd6(3)=xsd(8)
xsd6(4)=xsd(5)
ysd6(1)=ysd(1)
ysd6(2)=ysd(4)
ysd6(3)=ysd(8)
ysd6(4)=ysd(5)
zsd6(1)=zsd(1)
zsd6(2)=zsd(4)
zsd6(3)=zsd(8)
zsd6(4)=zsd(5)
b(1)=xsd6(3)-xsd6(1)
b(2)=ysd6(3)-ysd6(1)
b(3)=zsd6(3)-zsd6(1)
c(1)=xsd6(4)-xsd6(2)
c(2)=ysd6(4)-ysd6(2)
c(3)=zsd6(4)-zsd6(2)
call cross(c, b,crossproduct)
norm(:)=crossproduct/(crossproduct(1)**2+crossproduct(2)**2+crossproduct(3)**2)**0.5
area_isd=((crossproduct(1)**2+crossproduct(2)**2+crossproduct(3)**2)**0.5)/2
END IF
J 是面,我遍历各个面中的点并找到对角线的叉积。
我想知道这两种方法有什么问题以及纠正方法。如果有人能给我一条前进的道路,我会很高兴。