Академический Документы
Профессиональный Документы
Культура Документы
Graphic
Utilities
G1
TABLE OF CONTENTS
Page
G.1.
G.2.
G.3.
Introduction
Hex8 Element Plotting Module
G.2.1.
Usage . . . . . . . . .
G.2.2.
Source Code . . . . . . .
G.2.3.
Individual Element Example Plots
G.2.4.
Multiple Element Example Plots
Hex20 Element Plotting Module
G.3.1.
Usage . . . . . . . . .
G.3.2.
Source Code . . . . . . .
G.3.3.
Individual Element Example Plots
G2
. .
.
.
.
.
. .
.
. .
. .
.
. .
.
.
. .
.
. .
. .
.
. .
.
.
. .
.
. .
. .
.
. .
.
. . . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
G3
G3
G4
G14
G14
G14
G15
G18
G28
G28
G.2
G.1. Introduction
This Appendix collects a set of application-independent graphic utilities organized as Mathematica
modules. By application independent is meant that these modules are reusable across different
FEM application programs that do not necessarily simulate structures.
G.2. Hex8 Element Plotting Module
The Mathematica module PlotHex8Elem produces plots of the 8-node hexahedron finite element
described in Chapter 11. The module aims to provide a comprehensive set of plotting options to
display an individual element of that particular configuration.
Although the module can display multiple elements, it is not recommended for showing a finite
element mesh because PlotHex8Elem focuses on local (intrinsic) element properties. As a matter
of fact, such multiple elements need not be connected in any way, as they would be in a mesh. That
lack of restrictions has some practical uses, for example to illustrate initial and final configurations
of the same element. Another module, called PlotHex8Mesh and described in Section ?, is more
suitable for plotting a hexahedral mesh.
PlotHex8Elem
Driver that generates plot
stream by interpreting
"plotwhat" commands,
and displays or saves
plot image
PlotHex8Faces
PlotHex8Lines
PlotHex8Points
PlotHex8Options
PlotHex8Macro
Hex8CarInterp
Expands a macro
command keyword into
sequence of low-level
instructions
Do not confuse point which is a distinguished element location such as a nodal point (a corner in Hex8) or a Gauss
G3
G.2.1. Usage
The module may be invoked in either of two ways:
PlotHex8[xyzhex,plotwhat,plotspecs]
phex= PlotHex8[xyzhex,plotwhat,plotspecs]
(G.1)
The first form outputs a plot image to the screen. The second form displays no image but places the
plot object into phex as function return. A logical flag provided in argument plotspecs determines
the appropriate calling form, as described below.
The arguments are:
xyzhex
plotwhat
plotspecs
G4
G.2
Command
What to plot
"corners"
or "nodes"
"diagonals"
"edges" or
"sides"
{ 1,2 },{ 1,4 },{ 1,5 },{ 2,3 },{ 2,6 },{ 3,4 },
{ 3,7 },{ 4,8 },{ 5,6 },{ 5,8 },{ 6,7 },{ 7,8 }
"faces"
"fcenters"
"gp111"
{ { 0,0,0 },"G1" }
"gp222"
"labnaxes"
Natural axes labels {, , } placed
or "labhaxes" near tips. Axis tips are not plotted
as points.
"medians"
"medsurf" or
"medplanes"
Median surfaces = 0, = 0,
and = 0
"naxes" or
"haxes"
Axis-tip distances from faces may be adjusted with the { "tips", } option; see Table ?
G5
Format
What to plot
{n}
n: integer in range 18
{ n,label }
{ n1,n2 }
{m}
{ ,, }
{ { ,, },label }
{ { 1,1,1 },
{ 2,2,2 } }
{ " ",c }
c: coordinate of surface =c
{ "",c }
c: coordinate of surface =c
{ "",c }
c: coordinate of surface =c
If c is outside the range [1, 1], the plotted plane is outside the element, but will be bounded
by the [1, 1] range of of the other two coordinates.
G6
G.2
Description
Defaults
{ "fcolor",color }
Mathematica default
for 3D graphics (these
defaulst may vary with
version).
{ "lcolor",color }
Black
{ "pcolor",color }
Black
{ "style",
{ fontfamily,
fontsize,fontslant } }
{ "psize",size }
Point size: 6 pt
{ "ethick",thickness }
Polygon edge
thickness: 1.25 pt
{ "lthick",thickness }
Line thickness: 2 pt
{ "offset",
{
x,
y,
z } }
x= x= z=0.04.
{ "tips", }
= 1.5, whence
axes tips stick 50%
outside element.
Note: The label offset specification in terms of coordinate values is awkward, but unfortunately
Mathematica lacks the ability to specify an absolute distance between graphic objects in points.
G7
Description
Recommended specifications
Nsub
boxrat
view
light
imgsiz
showbox
False
showxyz
False
G8
G.2
PlotHex8Elem[xyzhex_,plotwhat_,plotspecs_]:=Module[{i,j,k,m,n,p,e,
ip,n1,n2,np,ne=1,what,w,whead,wlen,kw,w1,w2,w1head,w1len,w2head,w2len,
F,L,P,expMC,Nsub,boxrat,view,light,imgsiz,showbox,showxyz,plotsave,
boxdim,ps,black,red,blue,psizdef=6,ethidef=1.25,lthidef=2,tipsdef=1.5,
styledef={TextStyle->{FontFamily->"Times",FontSize->14,
FontWeight->"Plain"}},offsetdef={0.04,0.04,0.04},plotopt,
axespec=False,axeslab=" ",polyfill,polyedge,lines,points,labels,
optkey,key,dfun,xyzc=xyzhex,mulele,phex,modname="PlotHex8Elem:"},
optkey[key_]:=StringLength[key]>=4&&Length[StringPosition[
validoptkeys,StringTake[key,4]]]>0;
validoptkeys="ethi fcol pcol lcol lthi psiz styl offs tips";
polyfill=polyedge=lines=points=labels={};
plotopt={styledef,psizdef,ethidef,lthidef,offsetdef,tipsdef};
{Nsub,boxrat,view,light,imgsiz,showbox,showxyz,plotsave}=plotspecs;
If [showxyz, axespec=True; axeslab={"x","y","z"}];
{black,red,blue}={RGBColor[0,0,0],RGBColor[1,0,0],RGBColor[0,0,1]};
mulele=Length[Dimensions[xyzhex]]==3; If [mulele, ne=Length[xyzhex]];
np=Length[plotwhat]; If [np<=0,Return[]];
For [e=1,e<=ne,e++, For [ip=1,ip<=np,ip++, p=False; what=plotwhat[[ip]];
whead=Head[what]; wlen=Length[what]; If [mulele, xyzc=xyzhex[[e]]];
If [wlen==0,
If [whead==String,
{{F,L,P},expMC}=PlotHex8Macro[what,plotopt,plotspecs];
If [F>0, {polyfill,polyedge}=PlotHex8Faces[
xyzc,expMC,Nsub,polyfill,polyedge]; p=True];
If [L>0, lines=PlotHex8Lines[xyzc,expMC,L,lines]; p=True];
If [P>0, {points,labels}=PlotHex8Points[
xyzc,expMC,plotopt,points,labels]; p=True];
If [P<0, ps=plotopt[[2]]; plotopt[[2]]=0; {points,labels}=
PlotHex8Points[xyzc,expMC,plotopt,points,labels];
plotopt[[2]]=ps; p=True]];
If [whead==Integer, {points,labels}=PlotHex8Points[
xyzc,{{what}},plotopt,points,labels]; p=True];
];
If [wlen==1, {w1}=what; w1head=Head[w1]; w1len=Length[w1];
If [w1head==Integer,
If [w1>=1&&w1<=8, {points,labels}=PlotHex8Points[
xyzc,{w1},plotopt,points,labels]; p=True];
If [w1>=102&&w1<=807, n1=Floor[w1/100]; n2=w1-100*n1;
lines=PlotHex8Lines[xyzc,{{n1,n2}},1,lines]; p=True]];
If [whead==List&&wlen==3,
{points,labels}=PlotHex8Points[
xyzc,what,plotopt,points,labels]; p=True];
];
If [wlen==2, {w1,w2}=what; w1head=Head[w1]; w1len=Length[w1];
If [w1head==String,
If [optkey[w1],
{plotopt,polyfill,polyedge,lines,points,labels}=
PlotHex8Options[what,{plotopt,polyfill,polyedge,
lines,points,labels}]; p=True];
If [w1==" "||w1==""||w1=="",
{polyfill,polyedge}=PlotHex8Faces[xyzc,{what},
Nsub,polyfill,polyedge]; p=True]];
If [w1head==Integer, w2head=Head[w2];
If [w2head==Integer, lines=PlotHex8Lines[xyzc,{what},
Nsub,lines]; p=True];
If [w2head==String, {points,labels}=PlotHex8Points[
xyzc,{what},plotopt,points,labels]; p=True]];
If [w1head==List, w2head=Head[w2];
If [w2head==List, lines=PlotHex8Lines[xyzc,{what},
Nsub,lines]; p=True];
If [w2head==String, {points,labels}=PlotHex8Points[
xyzc,{what},plotopt,points,labels]; p=True]];
];
G9
PlotHex8Faces[xyzc_,facelist_,Nsub_,polyfinc_,polyeinc_]:=
Module[ {i,j,kf=Length[polyfinc],ke=Length[polyeinc],
n=Nsub,nf=Length[facelist],if,ic,cval,
am,ap,bm,bp,xyz1,xyz2,xyz3,xyz4,polyfill,polyedge},
If [n<=0||nf<=0, Return[polyfinc,polyeinc]];
polyfill=Join[polyfinc,Table[0,{n^2*nf}]];
polyedge=Join[polyeinc,Table[0,{n^2*nf}]];
For [if=1,if<=nf,if++, {c,cval}=facelist[[if]]; ic=c;
If [Head[c]==String, jc=StringPosition[" ",c];
If [jc=={},Continue[]]; {{ic,ic}}=jc ];
For [i=1,i<=n,i++, am=(2*i-n-2)/n; ap=(2*i-n)/n;
For [j=1,j<=n,j++, bm=(2*j-n-2)/n; bp=(2*j-n)/n;
1= 2= 3= 4=1=2=3=4=1=2=3=4=cval;
If [ic==1, 1=4=N[am]; 2=3=N[ap];
1=2=N[bm]; 3=4=N[bp]];
If [ic==2, 1=4=N[am]; 2=3=N[ap];
1= 2=N[bm]; 3= 4=N[bp]];
If [ic==3, 1= 4=N[am]; 2= 3=N[ap];
1=2=N[bm]; 3=4=N[bp]];
xyz1=Hex8CartInterp[xyzc,{ 1,1,1}];
xyz2=Hex8CartInterp[xyzc,{ 2,2,2}];
xyz3=Hex8CartInterp[xyzc,{ 3,3,3}];
xyz4=Hex8CartInterp[xyzc,{ 4,4,4}];
polyfill[[++kf]]=Graphics3D[Polygon[
{xyz1,xyz2,xyz3,xyz4}]];
polyedge[[++ke]]=Graphics3D[Line[
{xyz1,xyz2,xyz3,xyz4,xyz1}]];
]]];
Return[{polyfill,polyedge}]];
G10
G.2
PlotHex8Lines[xyzc_,linelist_,Nsub_,linesinc_]:=Module[
{i,k,nl=Length[linelist],lk,nn, 1, 2,d , beg, end,
xyz1,xyz2,nbeg,nend,n1,n2,lindef,node ,lines=linesinc},
node ={{-1,-1,-1},{1,-1,-1},{1,1,-1},{-1,1,-1},
{-1,-1,1}, {1,-1,1}, {1,1,1}, {-1,1,1}};
For [k=1,k<=nl,k++, lk=linelist[[k]]; nbeg=nend=Null;
If [Length[lk]==2,{nbeg,nend}=lk]; lindef=False;
If [Length[nbeg]==3&&Length[nend]==3,
beg=nbeg; end=nend; lindef=True];
If [Head[nbeg]==Integer&&Head[nend]==Integer,
n1=Min[nbeg,nend]; n2=Max[nbeg,nend];
If [n1>=1&&n1<=20&&n2>=1&&n2<=20, lindef=True;
beg=node [[n1]]; end=node [[n2]];
]];
If [!lindef||Nsub<=0, Return[lines]];
2= beg; d =( end- beg)/Nsub;
For [i=1,i<=Nsub,i++, 1= 2; 2= 1+d ;
xyz1=Hex8CartInterp[xyzc, 1];
xyz2=Hex8CartInterp[xyzc, 2];
AppendTo[lines,Graphics3D[Line[{xyz1,xyz2}]]]];
];
Return[lines]];
Figure G.5. Module PlotHex8Lines that plots lines joining two specified points; for
example hexahedron edges.
PlotHex8Points[xyzc_,pointlist_,plotopt_,pointsinc_,labelsinc_]:=
Module[{ip,np=Length[pointlist],k,pk,pklen,pdef,plab,p ,xyzp,
pdeflen,style,psize,ethik,lthik,offset,points=pointsinc,
labels=labelsinc}, {style,psize,ethik,lthik,offset}=plotopt;
For [k=1,k<=np,k++, pk=pointlist[[k]]; pklen=Length[pk];
If [pklen>3, Continue[]]; pdef=plab=p =Null;
If [pklen==1, {pdef}=pk]; If [pklen==2, {pdef,plab}=pk];
If [pklen==0||pklen==3, pdef=pk]; pdeflen=Length[pdef];
If [pdeflen==0, p=pdef]; If [pdeflen==3, p =pdef];
If [Head[p]==Integer, If[p<1||p>8,Continue[]];
xyzp=xyzc[[p]]];
If [Head[p ]==List, xyzp=Hex8CartInterp[xyzc,p ]];
If [Head[plab]==String, AppendTo[labels,
Graphics3D[Text[plab,xyzp+offset,style]]]];
If [psize>0,
AppendTo[points,Graphics3D[Point[xyzp]]]];
];
Return[{points,labels}]];
Figure G.6. Module PlotHex8Lines that plots specified points (for example, nodes), and
optionally writes labels nearby.
Figure G.7. Module Hex8CartInterp that returns {x, y, z} of a point, given its natural
(hexahedral) coordinates.
G11
Figure G.8. Module PlotHex8Options that injects non default options in the plot command stream.
G12
G.2
PlotHex8Macro[keyw_,plotopt_,plotspecs_]:=Module[{i,node ,
t=plotopt[[6]],Nsub=plotspecs[[1]],FLP={0,0,0},
keylen=StringLength[keyw],kw=Null},
If [keylen<5, Return[{FLP,Null}]]; kw=StringTake[keyw,5];
node ={{-1,-1,-1},{1,-1,-1},{1,1,-1},{-1,1,-1},
{-1,-1,1}, {1,-1,1}, {1,1,1}, {-1,1,1}};
If [kw=="faces", FLP[[1]]=1; Return[{FLP,
{{" ",-1},{" ",1},{"",-1},{"",1},{"",-1},{"",1}}}]];
If [kw=="medsu"||kw=="medpl", FLP[[1]]=1; Return[{FLP,
{{" ",0},{"",0},{"",0}}}]];
If [kw=="edges"||kw=="sides", FLP[[2]]=1; Return[{FLP,
{{1,2},{1,4},{1,5},{2,3},{2,6},{3,4},
{3,7},{4,8},{5,6},{5,8},{6,7},{7,8}} }]];
If [kw=="diago", FLP[[2]]=Nsub; Return[{FLP,
{{1,7},{2,8},{3,5},{4,6}}}]];
If [kw=="naxes"||kw=="haxes", FLP[[2]]=1; Return[{FLP,
{{{-1,0,0},{t,0,0}},{{0,-1,0},{0,t,0}},{{0,0,-1},{0,0,t}}}}]];
If [kw=="media", FLP[[2]]=1; Return[{FLP,{{{-1,0,0},{1,0,0}},
{{0,-1,0},{0,1,0}},{{0,0,-1},{0,0,1}}}}]];
If [kw=="corne"||kw=="nodes", FLP[[3]]=1; Return[{FLP,
Table[{i},{i,8}]}]];
If [kw=="labco"||kw=="labno", FLP[[3]]=1; Return[{FLP,
Table[{i,ToString[i]},{i,8}]}]];
If [kw=="fcent", FLP[[3]]=1; Return[{FLP,
{{-1,0,0},{1,0,0},{0,-1,0},{0,1,0},{0,0,-1},{0,0,1}}}]];
If [kw=="labfc", FLP[[3]]=1; ; Return[{FLP,
{{{-1,0,0},"C1485"},{{1,0,0}, "C2376"},{{0,-1,0},"C1265"},
{{ 0,1,0},"C3487"},{{0,0,-1},"C1234"},{{0,0,1}, "C5678"}}}]];
If [kw=="labna"||kw=="labha", FLP[[3]]=-1; Return[{FLP,
{{{t,0,0}," "},{{0,t,0},""},{{0,0,t},""}}}]];
If [kw=="gp111", FLP[[3]]=1; Return[{FLP,{{{0,0,0},"G1"}}}]];
If [kw=="gp222", FLP[[3]]=1; Return[{FLP,
Table[{N[node [[i]]/Sqrt[3]],"G"<>ToString[i]},{i,8}]}]];
Return[{FLP,Null}]];
Figure G.9. Module PlotHex8Macro that receives a macro command keyword and emits a stream of
equivalent low-level commands.
G13
could be externally controlled with additional arguments in the plotspecs argument, but it would be just as
easy (in fact, faster) to go in and change the source code. For example, to pass from the AmbientLight diffuseisotropic lighting to light point sources it would be necessary to modify the Show command options, which is relatively easy. Note that the second Show statement contains a specification, namely, DisplayFunction->dfun,
that is Mathematica version dependent; it was changed in version 6.
Remark G.2. Line Plotting Logic. PlotHex8Elem draws the line joining two specified points as a straight
line in the Cartesian (physical) space if and only if it knows that to be the case. That happens for edges and
medians since mapping from {, , } to {x, y, z} is linear along lines where two hexahedral coordinates are
constant. Aside from that PlotHex8Elem assumes a curved line, and draws it in piecewise linear manner with
Nsub segments. To illustrate, observe that the diagonals displayed in Figure ?(e) are curved. For example,
the diagonal joining corner 1 to the opposite corner 7 has the equation = = in natural (hexahedral)
coordinates; plugging into the iso-P map gives a quadratic parametric form in {x, y, z}.
{ { 0,0,0 },
{ 0,0,0 }*c,
{ 2,0,0 },
{ 2,0,0 }*c,
{ 2,1,0 },
{ 0,1,0 },
{ 2,1,0 }*c, { 0,1,0 }*c };
(G.2)
G.3
(a)
6
(b)
(c)
2
3
(d)
(e)
6
(f)
5
8
7
G5 G8
G6
G7
1.5
0.5
2
0.4
0.3
G1
1
0.2
G4
G2
G3
2
0.1
0
0
0.25
0.5
0.75
1
Figure G.10. Sample plots of an individual Hex8 element, with Nsub=4, boxrat={ 1,1,1 }, view={ 3,2,1.5 },
and imgsiz=300 chosen for all: (a) shows faces, edges and labeled corners; (b) same as (a) except for white
lighting set via light=GrayLevel[1] and corner labels are omitted; (c) shows median faces and labeled natural
axes , , (axis labels slightly moved with Illustrator for better view); (d) shows four natural coordinate surfaces
= c, c = 1, 1/3, 1/3, 1 plus the labeled axis; (e) shows green-colored diagonals (curved because element
has variable metric) and red-colored labeled sample points of the 2 2 2 Gauss rule note that Gauss point fall
on the diagonals; (f) shows all lines (edges and face polygon edges) plotted in black with same thickness of 2.5
pt, ambient light set to yellow via light=Hue[0.2], and labeled {x, y, z} axes drawn along plotting box edges.
G15
(a)
(b)
y
0
0.5
1
1.5
2
-2
0
4
6
0.1
z
0.075
0.05 z
0.025
0
0
5
-5
4.5
5
x
5.5
G16
G.3
PlotHex20Elem
Driver that generates plot
stream by interpreting
"plotwhat" commands,
and displays or saves
plot image
PlotHex20Faces
PlotHex20Lines
PlotHex20Points
PlotHex20Options
PlotHex20Macro
Hex20CarInterp
Expands a macro
command keyword into
sequence of low-level
instructions
The overall organization is diagrammed in Figure ?. On comparing Figures ? and ?, it is plain the
organization mimics that of 8-node tetrahedron plotting module PlotHex8Elem, which is described
in ?. In fact over 95% of the code is identical. In addition PlotHex20Elem is invoked with the
same arguments, but has some additional plotting commands because of the presence of midnodes.
Module PlotHex20Elem is actually a driver that interprets an array of plot what commands, and calls subordinate modules PlotHex20Faces, PlotHex20Lines, PlotHex20Points,
PlotHex20Options, and PlotHex20Macro as appropriate to construct the plot stream. Another
subordinate module, Hex20CarInterp, is called by PlotHex20Faces, PlotHex20Lines, and
PlotHex20Points to map natural to Cartesian coordinates using the Hex20 shape functions.
Once all instructions are processed, the plot image is created using the built in Show function. The
image is either output to the screen, or returned as a list, according to input specifications.
As in the other Sections, the abbreviation pt denotes a printer point, which is a length dimension
of 0.35146 mm = 0.013837 inches = (1/72.27) inches.
G17
G.3.1. Usage
The module may be invoked in either of two ways:
PlotHex20[xyzhex,plotwhat,plotspecs]
phex= PlotHex20[xyzhex,plotwhat,plotspecs]
(G.3)
The first form outputs a plot image to the screen. The second form displays no image but places the
plot object into phex as function return. A logical flag provided in argument plotspecs determines
the appropriate calling form, as described below.
The arguments are:
xyzhex
plotwhat
plotspecs
G18
G.3
Command
What to plot
"corners"
"midpoints"
"nodes"
"diagonals"
"edges" or
"sides"
{ 1,2 },{ 1,4 },{ 1,5 },{ 2,3 },{ 2,6 },{ 3,4 },
{ 3,7 },{ 4,8 },{ 5,6 },{ 5,8 },{ 6,7 },{ 7,8 }
"faces"
"fcenters"
"gp111"
{ { 0,0,0 },"G1" }
"gp222"
See Table ?.
"gp333"
"labcor"
"labmid"
Labeled midnodes
"labnodes"
Labeled nodes
"labfcent"
See Table ?.
"labnaxes"
Natural axes labels {, , } placed
or "labhaxes" near tips. Axis tips are not plotted
See Table ?.
"medians"
"medsurf" or
"medplanes"
Median surfaces = 0, = 0,
and = 0
"naxes" or
"haxes"
Axis-tip distances from faces may be adjusted with the { "tips", } option; see Table ?
G19
Format
What to plot
{n}
n: integer in range 18
{ n,label }
{ n1,n2 }
{m}
{ ,, }
{ { ,, },label }
{ { 1,1,1 },
{ 2,2,2 } }
{ " ",c }
c: coordinate of surface =c
{ "",c }
c: coordinate of surface =c
{ "",c }
c: coordinate of surface =c
If c is outside the range [1, 1], the plotted plane is outside the element, but will be bounded
by the [1, 1] range of of the other two coordinates.
G20
G.3
Description
Defaults
{ "fcolor",color }
Mathematica default
for 3D graphics (these
defaulst may vary with
version).
{ "lcolor",color }
Black
{ "pcolor",color }
Black
{ "style",
{ fontfamily,
fontsize,fontslant } }
{ "psize",size }
Point size: 6 pt
{ "ethick",thickness }
Polygon edge
thickness: 1.25 pt
{ "lthick",thickness }
Line thickness: 2 pt
{ "offset",
{
x,
y,
z } }
x= x= z=0.04.
{ "tips", }
= 1.5, whence
axes tips stick 50%
outside element.
Note: The label offset specification in terms of coordinate values is awkward, but unfortunately
Mathematica lacks the ability to specify an absolute distance between graphic objects in points.
G21
Description
Recommended specifications
Nsub
boxrat
view
light
imgsiz
showbox
False
showxyz
False
G22
G.3
PlotHex20Elem[xyzhex_,plotwhat_,plotspecs_]:=Module[{i,j,k,m,n,p,e,
ip,n1,n2,np,ne=1,what,w,whead,wlen,kw,w1,w2,w1head,w1len,w2head,w2len,
F,L,P,expMC,Nsub,boxrat,view,light,imgsiz,showbox,showxyz,plotsave,
boxdim,ps,black,red,blue,psizdef=6,ethidef=1.25,lthidef=2,tipsdef=1.5,
styledef={TextStyle->{FontFamily->"Times",FontSize->14,
FontWeight->"Plain"}},offsetdef={0.04,0.04,0.04},plotopt,
axespec=False,axeslab=" ",polyfill,polyedge,lines,points,labels,
optkey,key,dfun,xyzc=xyzhex,mulele,phex,modname="PlotHex20Elem:"},
optkey[key_]:=StringLength[key]>=4&&Length[StringPosition[
validoptkeys,StringTake[key,4]]]>0;
validoptkeys="ethi fcol pcol lcol lthi psiz styl offs tips";
polyfill=polyedge=lines=points=labels={};
plotopt={styledef,psizdef,ethidef,lthidef,offsetdef,tipsdef};
{Nsub,boxrat,view,light,imgsiz,showbox,showxyz,plotsave}=plotspecs;
If [showxyz, axespec=True; axeslab={"x","y","z"}];
{black,red,blue}={RGBColor[0,0,0],RGBColor[1,0,0],RGBColor[0,0,1]};
mulele=Length[Dimensions[xyzhex]]==3; If [mulele, ne=Length[xyzhex]];
np=Length[plotwhat]; If [np<=0,Return[]];
For [e=1,e<=ne,e++, For [ip=1,ip<=np,ip++, p=False; what=plotwhat[[ip]];
whead=Head[what]; wlen=Length[what]; If [mulele, xyzc=xyzhex[[e]]];
If [wlen==0,
If [whead==String,
{{F,L,P},expMC}=PlotHex20Macro[what,plotopt,plotspecs];
If [F>0, {polyfill,polyedge}=PlotHex20Faces[
xyzc,expMC,Nsub,polyfill,polyedge]; p=True];
If [L>0, lines=PlotHex20Lines[xyzc,expMC,Nsub,lines]; p=True];
If [P>0, {points,labels}=PlotHex20Points[
xyzc,expMC,plotopt,points,labels]; p=True];
If [P<0, ps=plotopt[[2]]; plotopt[[2]]=0; {points,labels}=
PlotHex20Points[xyzc,expMC,plotopt,points,labels];
plotopt[[2]]=ps; p=True]];
If [whead==Integer, {points,labels}=PlotHex20Points[
xyzc,{{what}},plotopt,points,labels]; p=True];
];
If [wlen==1, {w1}=what; w1head=Head[w1]; w1len=Length[w1];
If [w1head==Integer,
If [w1>=1&&w1<=8, {points,labels}=PlotHex20Points[
xyzc,{w1},plotopt,points,labels]; p=True];
If [w1>=102&&w1<=2019, n1=Floor[w1/100]; n2=w1-100*n1;
lines=PlotHex20Lines[xyzc,{{n1,n2}},Nsub,lines]; p=True]];
If [whead==List&&wlen==3,
{points,labels}=PlotHex20Points[
xyzc,what,plotopt,points,labels]; p=True];
];
If [wlen==2, {w1,w2}=what; w1head=Head[w1]; w1len=Length[w1];
If [w1head==String,
If [optkey[w1],
{plotopt,polyfill,polyedge,lines,points,labels}=
PlotHex20Options[what,{plotopt,polyfill,polyedge,
lines,points,labels}]; p=True];
If [w1==" "||w1==""||w1=="",
{polyfill,polyedge}=PlotHex20Faces[xyzc,{what},
Nsub,polyfill,polyedge]; p=True]];
If [w1head==Integer, w2head=Head[w2];
If [w2head==Integer, lines=PlotHex20Lines[xyzc,{what},
Nsub,lines]; p=True];
If [w2head==String, {points,labels}=PlotHex20Points[
xyzc,{what},plotopt,points,labels]; p=True]];
If [w1head==List, w2head=Head[w2];
If [w2head==List, lines=PlotHex20Lines[xyzc,{what},
Nsub,lines]; p=True];
If [w2head==String, {points,labels}=PlotHex20Points[
xyzc,{what},plotopt,points,labels]; p=True]];
];
G23
G24
G.3
PlotHex20Lines[xyzc_,linelist_,Nsub_,linesinc_]:=Module[
{i,k,nl=Length[linelist],lk,nn, 1, 2,d , beg, end,
xyz1,xyz2,nbeg,nend,n1,n2,lindef,nod ,lines=linesinc},
nod ={{-1,-1,-1},{1,-1,-1},{1,1,-1},{-1,1,-1},
{-1,-1,1}, {1,-1,1}, {1,1,1}, {-1,1,1},
{0,-1,-1}, {1,0,-1}, {0,1,-1},{-1,0,-1},
{-1,-1,0}, {1,-1,0}, {1,1,0}, {-1,1,0},
{0,-1,1}, {1,0,1}, {0,1,1}, {-1,0,1}};
For [k=1,k<=nl,k++, lk=linelist[[k]]; nbeg=nend=Null;
If [Length[lk]==2,{nbeg,nend}=lk]; lindef=False;
If [Length[nbeg]==3&&Length[nend]==3,
beg=nbeg; end=nend; lindef=True];
If [Head[nbeg]==Integer&&Head[nend]==Integer,
n1=Min[nbeg,nend]; n2=Max[nbeg,nend];
If [n1>=1&&n1<=20&&n2>=1&&n2<=20, lindef=True;
beg=nod [[n1]]; end=nod [[n2]];
]];
If [!lindef||Nsub<=0, Return[lines]];
2= beg; d =( end- beg)/Nsub;
For [i=1,i<=Nsub,i++, 1= 2; 2= 1+d ;
xyz1=Hex20CartInterp[xyzc, 1];
xyz2=Hex20CartInterp[xyzc, 2];
AppendTo[lines,Graphics3D[Line[{xyz1,xyz2}]]]];
];
Return[lines]];
Figure G.19. Module PlotHex20Lines that plots lines joining two specified points; for
example hexahedron edges.
PlotHex20Points[xyzc_,pointlist_,plotopt_,pointsinc_,labelsinc_]:=
Module[{ip,np=Length[pointlist],k,pk,pklen,pdef,plab,p,xyzp,
pdeflen,style,psize,ethik,lthik,offset,tips,points=pointsinc,
labels=labelsinc}, {style,psize,ethik,lthik,offset,tips}=plotopt;
For [k=1,k<=np,k++, pk=pointlist[[k]]; pklen=Length[pk];
If [pklen>3, Continue[]]; pdef=plab=p=Null;
If [pklen==1, {pdef}=pk]; If [pklen==2, {pdef,plab}=pk];
If [pklen==0||pklen==3, pdef=pk]; pdeflen=Length[pdef];
If [pdeflen==0, p=pdef]; If [pdeflen==3, p=pdef];
If [Head[p]==Integer, If[p<1||p>20,Continue[]];
xyzp=xyzc[[p]]];
If [Head[p]==List, xyzp=Hex20CartInterp[xyzc,p]];
If [Head[plab]==String, AppendTo[labels,
Graphics3D[Text[plab,xyzp+offset,style]]]];
If [psize>0,
AppendTo[points,Graphics3D[Point[xyzp]]]];
];
Return[{points,labels}]];
Figure G.20. Module PlotHex20Lines that plots specified points (for example, nodes), and
optionally writes labels nearby.
G25
Figure G.21. Module Hex20CartInterp that returns {x, y, z} of a point, given its natural
(hexahedral) coordinates.
PlotHex20Options[opt_,graphicsinc_]:=Module[{w1,w2,key14,key24,
w2head,w2len,R,G,B,color,style,psize,ethik,lthik,offset,tips,
plotopt,polyfill,polyedge,lines,points,labels},
{plotopt,polyfill,polyedge,lines,points,labels}=graphicsinc;
{style,psize,ethik,lthik,offset,tips}=plotopt;
{w1,w2}=opt; w2head=Head[w2]; w2len=Length[w2];
key14=StringTake[w1,4]; key24=StringTake[w1,{2,4}];
If [key24=="col", R=G=B=0; color=False;
If [w2head==String,
If [w2=="black", color=True];
If [w2=="red",
color=True; R=1];
If [w2=="green", color=True; G=1];
If [w2=="blue", color=True; B=1]];
If [w2head==List&&w2len==3, color=True; {R,G,B}=w2];
If [key14=="pcol"&&color,
AppendTo[points,Graphics3D[RGBColor[R,G,B]]]];
If [key14=="lcol"&&color,
AppendTo[lines,Graphics3D[RGBColor[R,G,B]]]];
If [key14=="fcol"&&color,
AppendTo[polyfill,Graphics3D[RGBColor[R,G,B]]]]];
If [key14=="psiz", psize=6;
If [w2head==Integer||w2head==Real, psize=w2];
AppendTo[points,Graphics3D[AbsolutePointSize[psize]]]];
If [key14=="ethi", ethik=1.25;
If [w2head==Integer||w2head==Real, ethik=w2];
AppendTo[polyedge,Graphics3D[AbsoluteThickness[ethik]]]];
If [key14=="lthi", lthik=2;
If [w2head==Integer||w2head==Real, lthik=w2];
AppendTo[lines,Graphics3D[AbsoluteThickness[lthik]]]];
If [key14=="tips", tips=1.5;
If [w2head==Integer||w2head==Real, tips=w2]];
If [key14=="styl",
If [w2len==3, style={TextStyle->{FontFamily->w2[[1]],
FontSize->w2[[2]],FontWeight->w2[[3]]}}]];
If [key14=="offs", offset={0.04,0.04,0.04};
If [w2len==3, offset=w2]];
plotopt={style,psize,ethik,lthik,offset,tips};
Return[{plotopt,polyfill,polyedge,lines,points,labels}]];
Figure G.22. Module PlotHex20Options that injects non default options in the plot command stream.
G26
G.3
PlotHex20Macro[keyw_,plotopt_,plotspecs_]:=Module[{i,nod ,
t=plotopt[[6]],Nsub=plotspecs[[1]],FLP={0,0,0},gp333,
g=Sqrt[3/5],keylen=StringLength[keyw],kw=Null},
If [keylen<5, Return[{FLP,Null}]]; kw=StringTake[keyw,5];
nod ={{-1,-1,-1},{1,-1,-1},{1,1,-1},{-1,1,-1},
{-1,-1,1}, {1,-1,1}, {1,1,1}, {-1,1,1},
{0,-1,-1}, {1,0,-1}, {0,1,-1},{-1,0,-1},
{-1,-1,0}, {1,-1,0}, {1,1,0}, {-1,1,0},
{0,-1,1}, {1,0,1}, {0,1,1}, {-1,0,1}};
gp333={{-g,-g,-g},{0,-g,-g},{g,-g,-g},{-g,0,-g},{0,0,-g},{g,0,-g},
{-g, g,-g},{0, g,-g},{g, g,-g},{-g,-g,0},{0,-g,0},{g,-g,0},
{-g, 0, 0},{0, 0, 0},{g, 0, 0},{-g, g,0},{0, g,0},{g, g,0},
{-g,-g, g},{0,-g, g},{g,-g, g},{-g, 0,g},{0, 0,g},{g, 0,g},
{-g, g, g},{0, g, g},{g, g, g}};
If [kw=="faces", FLP[[1]]=1; Return[{FLP,
{{" ",-1},{" ",1},{"",-1},{"",1},{"",-1},{"",1}}}]];
If [kw=="medsu"||kw=="medpl", FLP[[1]]=1; Return[{FLP,
{{" ",0},{"",0},{"",0}}}]];
If [kw=="edges"||kw=="sides", FLP[[2]]=1; Return[{FLP,
{{1,2},{1,4},{1,5},{2,3},{2,6},{3,4},
{3,7},{4,8},{5,6},{5,8},{6,7},{7,8}} }]];
If [kw=="diago", FLP[[2]]=Nsub; Return[{FLP,
{{1,7},{2,8},{3,5},{4,6}}}]];
If [kw=="naxes"||kw=="haxes", FLP[[2]]=1; Return[{FLP,
{{{-1,0,0},{t,0,0}},{{0,-1,0},{0,t,0}},{{0,0,-1},{0,0,t}}}}]];
If [kw=="media", FLP[[2]]=1; Return[{FLP,{{{-1,0,0},{1,0,0}},
{{0,-1,0},{0,1,0}},{{0,0,-1},{0,0,1}}}}]];
If [kw=="corne", FLP[[3]]=1; Return[{FLP,Table[{i},{i,8}]}]];
If [kw=="nodes", FLP[[3]]=1; Return[{FLP,Table[{i},{i,20}]}]];
If [kw=="midno", FLP[[3]]=1; Return[{FLP,Table[{i},{i,9,20}]}]];
If [kw=="labco", FLP[[3]]=1; Return[{FLP,Table[{i,ToString[i]},{i,8}]}]];
If [kw=="labno", FLP[[3]]=1; Return[{FLP,Table[{i,ToString[i]},{i,20}]}]];
If [kw=="labmi", FLP[[3]]=1; Return[{FLP,Table[{i,ToString[i]},{i,9,20}]}]];
If [kw=="fcent", FLP[[3]]=1; Return[{FLP,
{{-1,0,0},{1,0,0},{0,-1,0},{0,1,0},{0,0,-1},{0,0,1}}}]];
If [kw=="labfc", FLP[[3]]=1; ; Return[{FLP,
{{{-1,0,0},"C1485"},{{1,0,0}, "C2376"},{{0,-1,0},"C1265"},
{{ 0,1,0},"C3487"},{{0,0,-1},"C1234"},{{0,0,1}, "C5678"}}}]];
If [kw=="labna"||kw=="labha", FLP[[3]]=-1; Return[{FLP,
{{{t,0,0}," "},{{0,t,0},""},{{0,0,t},""}}}]];
If [kw=="gp111", FLP[[3]]=1; Return[{FLP,{{{0,0,0},"G1"}}}]];
If [kw=="gp222", FLP[[3]]=1; Return[{FLP,
Table[{N[nod [[i]]/Sqrt[3]],"G"<>ToString[i]},{i,8}]}]];
If [kw=="gp333", FLP[[3]]=1; Return[{FLP,
Table[{N[gp333[[i]]],"G"<>ToString[i]},{i,27}]}]];
Return[{FLP,Null}]];
Figure G.23. Module PlotHex20Macro that receives a macro command keyword and emits a stream of
equivalent low-level commands.
G27
new plot feature needs to be inserted, the quickest way is to modify the source code.
Remark G.4. Line Plotting Logic. Unlike the Hex8 plotting module, any line that joins two points is assumed
to be curved, and is drawn with Nsub piecewise linear segments. The straight-line versus curved-line switch
logic described in Remark ? does not apply.
G28
G.3
(a)
(b)
(c)
5 20
6 17
18 7 19 8
13
16
14
1
15
12 11
3
10
(d)
(e)
(f)
x
G5 G8
G6 G7
G1
G2
G3
1.5
0.5 0
0.4
G4
0.2
z
0
0.25
0.5
0.75
y
Figure G.24. Sample plots of an individual Hex20 element, with Nsub=8, boxrat={ 1,1,1 }, view={ 4,3,1.5 },
and imgsiz=300 chosen for all: (a) shows faces, edges and labeled corners; (b) same as (a) except for white
lighting set via light=GrayLevel[1] and node labels are omitted; (c) shows median faces and labeled natural
axes , , (axis labels slightly moved with Illustrator for better view); (d) shows four natural coordinate surfaces
= c, c = 1, 1/3, 1/3, 1 plus the labeled axis; (e) shows corner and midnodes with different colors (black
and blue, repectively, while point size is boosted to 8 pt), green-colored diagonals (curved because element has
variable metric) and red-colored labeled sample points of the 2 2 2 Gauss rule (note that Gauss point fall on
the diagonals); (f) shows all lines (edges and face polygon edges) plotted in black with same thickness of 1.25 pt,
ambient light set to yellow via light=Hue[0.2], and labeled {x, y, z} axes drawn along plotting box edges.
xyzcor={{0,0,0}, {2,0,0}, {2,1,0}, {0,1,0},
{0,0,1}*c,{2,0,1}*c,{2,1,1}*c,{0,1,1}*c}/.c->.4;
mij={{1,2},{2,3},{3,4},{4,1},{1,5},{2,6},{3,7},{4,8},{5,6},{6,7},{7,8},{8,5}};
xyzhex=Table[0,{20}];
For [n=1,n<=20,n++,
If [n<=8,xyzhex[[n]]=xyzcor[[n]]; Continue[]];
{i,j}=mij[[n-8]]; xyzhex[[n]]=(xyzcor[[i]]+xyzcor[[j]])/2;
]; xyzhex[[10,3]]=-1/8; xyzhex[[11,3]]=1/8;
Nsub=8; boxrat={1,1,1}; view={4,3,1.5}; showbox=False; imgsiz=300;
light=GrayLevel[0]; showbox=False; showxyz=False; plotsave=False;
plotsp={Nsub,boxrat,view,light,imgsiz,showbox,showxyz,plotsave};
muaxis={{0,0,-1},{0,0,1.5}};
plotspwhite={Nsub,boxrat,view,GrayLevel[1],imgsiz,showbox,showxyz,plotsave};
plotspaxes={Nsub,boxrat,view,Hue[.15],imgsiz,showbox,True,plotsave};
PlotHex20Elem[xyzhex,{"faces","edges","labnodes"},plotsp];
PlotHex20Elem[xyzhex,{"faces","edges","nodes"},plotspwhite];
PlotHex20Elem[xyzhex,{"medsurf","edges","naxes","labnaxes"},plotsp];
PlotHex20Elem[xyzhex,{"edges","nodes",muaxis,{"offset",{0.0,0.05,0.0}},
{"psize",0},{{0,0,1.5},""},{"",-1},{"",-1/3},{"",1/3},{"",1}},plotsp];
PlotHex20Elem[xyzhex,{"edges","nodes",{"lcolor","green"},"diagonals",
{"pcolor","red"},"gp222"},plotsp];
PlotHex20Elem[xyzhex,{{"fcolor","black"},{"ethick",1.25},"faces",
{"lthick",1.25},"edges"},plotspaxes];
G29