I have a cube which is divided into 8 small cubes by bisecting each edge, I am trying to find out the surface area of each of the faces and the corresponding outward normals for them. This operation is done on a finite element mesh, so I have transformed the cube into the isoparametric form using shape(basis) functions and then tried to extract the area and normals.
Here is the part of the code:
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
The area of each surface of each small cube should be .25, for this case but this code it isn't returning so. The normals are also not correctly oriented, here the cube is aligned with the global axes so it should be either 1 or -1.
Note: a. This might always not be a cube, it can be any irregular hexahedron, so the areas will not be equal always thus we need to compute each of them. b. The faces might be oriented along different directions, so the isoparametric transformation is sort of necessary.
Also, I have approched this using vectors of each face, without using the isoparametric transformation, where I use the diagonals of face of the cube and compute their cross product to find the area and outward unit normal, that approch also fails when the element is not regular. That part of the code looks like:
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 being the faces, I loop over the points in the respective faces and find cross product of the diagonals.
I would like to know about what is wrong in both these approches and the way to correct it. I would be glad if some one could give me a way forward.