How to use a zLanguage script to produce parametric meshes?#
The association of zMaster module and zLanguage provides a very fast and efficient way to produce parametric meshes. One have simply to write a script describing the geometry of the mesh and run this script through zMaster module. To activate master objects, the code must be started with either -B option (batch meshing) or -G option (graphical interface).
A script started this way has access to a number of new object types.
Master zLanguage types#
POINT
: geometrical point.Operators :
+ -
: + and - operators. Right operand can be a POINT or a VECTOR object./
: multiply or divide coordinates by a double.=
: assignment operator. Right operand can be of type : double, POINT or VECTOR.
Methods :
print()
: print current value.
Members :
double x
(rw) : x coordinate.double y
(rw) : y coordinate.double z
(rw) : z coordinate.
LINE
: geometrical line.Operators :
=
: assignment operator. Right operand can be of type LINE.
Methods :
bind(POINT a, POINT b)
: anchors line between POINTs a and b. Care must be taken of order : a is always the final point and b the starting point.bind1(POINT a)
: set line start point.bind2(POINT a)
: set line end point.length()
: return the line length.set_nodes(int n, double p)
: set the number n of edge nodes on the line, with a geometrical progression of p (use p=1. for linear progression).print()
: print current value.
Members :
POINT p1
(rw) : start point. This member must not be requested before a call to bind() or bind1().POINT p2
(rw) : end point. This member must not be requested before a call to bind() or bind2().
ARC
: geometrical arc.Operators :
=
: assignment operator. Right operand can be of type ARC.
Methods :
set_center(POINT c)
: set center POINT c.set_parameters(POINT c, double r, double a1, double a2, POINT p1, POINT p2)
: set all arc parameters : center c, radius r, start angle a1 (rad), end angle a2 (rad), start POINT p1, end POINT p2.set_arc(POINT c, double r, double a1, double a2)
: initialize ARC to be an arc with center c, radius r, start angle a1 and end angle a2. POINTs p1 and p2 are internally automatically created.circle(POINT c, double r)
: initialize ARC to be a circle of center c and radius r.set_nodes(int n, double p)
: set the number n of edge nodes on the line, with a geometrical progression of p (use p=1. for linear progression).print()
: print current value.
Members :
double radius
(rw) : ARC radius.double aplha1
(rw) : start angle.double aplha2
(rw) : end angle.
RULED
: a ruled meshed domain (i.e. a domain with three or four sides, meshed with a ruled method).Operators :
=
: assignment operator. Right operand can be of type ARC.
Methods :
add(int s, EDGE e)
(an EDGE is either a LINE or an ARC) : add edge e to the s\(^\text{th}\) side of domain.remesh()
: mesh only this domain.reset()
: reinitialize this domain.print()
: print current value.
Members :
int method
(rw) : linear or not method (see zMaster manual for more information).int fake4
(rw) : set this member to 1 for three sides domains.string element_type
(rw) : element type to be created.string elset_type
(rw) : give an elset name to the domain
DELAUNAY
: a Delaunay meshed domain.Methods :
add(EDGE e)
(an EDGE is either a LINE or an ARC) : add edge e. Please respect order (see zMaster manual for more informations) !remesh()
: mesh only this domain.reset()
: reinitialize this domain.print()
: print current value.
Members :
int method
(rw) : method (see zMaster manual for more information).double propagation
(rw) : method parameter.double critical_angle
(rw) : method parameter.string element_type
(rw) : element type to be created.string elset_type
(rw) : give an elset name to the domain
PAVING
: a paving meshed domain.Methods :
add(EDGE e)
(an EDGE is either a LINE or an ARC) : add edge e. Please respect order (see zMaster manual for more information) !remesh()
: mesh only this domain.reset()
: reinitialize this domain.print()
: print current value.
Members :
double seam_factor
(rw) : method parameter.double size_factor
(rw) : method parameter.string element_type
(rw) : element type to be created.
Memory management#
Memory is automatically managed inside zLanguage : objects are created and
destroyed on demand, when it is necessary. As l and zMaster are two
separate modules of Z-set, the user has to tell l which objects have not
to be deleted (because these objects, for instance PAVING
will be
used by zMaster). This is done using the method link()
: all
master objects have a method named link()
which ensures that the
current object and all its attachments will not be deleted. Usually,
one has only to call link()
for domains since this call ensures also
that all lines, arc, points, etc… belonging to this domain will not be
deleted.
Interfacing with graphical user interface#
It is possible to run script in zMaster graphical user interface : choose ’Run script’ option in ’Action’ menus. A choice window appears with two script lists : the top list contains scripts located in Z-set directories ($Z7PATH/lib/Scripts), the second list contains scripts in the current working directory. Choose a script then click on ’Setup’ button : anew window will appear asking for some parameters with default values. How is it possible?
To activate this possibility, one has only to put at the beginning of its script a special commented header describing the script and its parameters. The syntax of this header is as follows:
//
// MASTERSCRIPT
// begin
// STRING name Name A0
// STRING etype Element c2d
// double cx Cx 0.
// double cy Cy 0.
// double alpha Angle 0.
// double radius Radius 1.
// double rel_dist rel_dist 0.66
// int nedges Nedges 4
// bool use_inner_line InnerLine 1
// end
//
The two first lines and the last line are mandatory and conventional. The remainder lines describe some global variables with their type (first word), the variable name inside the script (second word), the name which will appears in dialog window (third word) and at last a default value. Currently only types int, bool, double and string are supported (it is not possible to declare an ARRAY this way, for instance).
One has only to use these global variables inside the script : these variables will be automatically initialized according to the user specifications. A simple example is :
//
// MASTERSCRIPT
// begin
// double cx Cx 0.
// double cy Cy 0.
// end
//
void main()
{
global double cx,cy;
("Got cx="+cx+" and cy="+cy+endl).print();
}
Examples#
This section contains some example (very easy to more complex) concerning the use of zLanguage to make parametric meshes.
\(\bullet\) A very simple example : how to mesh a unit square with paving method. Put the following lines in a file named ’square.z7p’.
void main()
{
POINT a,b,c,d;
LINE c1,c2,c3,c4;
PAVING square;
a.x=0.; a.y=0.; b.x=1.; b.y=0.;
c.x=1.; c.y=1.; d.x=0.; d.y=1.;
//
c1.bind(b,a); c2.bind(c,b);
c3.bind(d,c); c4.bind(a,d);
//
c1.set_nodes(5,1.); c2.set_nodes(6,1.);
c3.set_nodes(7,1.); c4.set_nodes(8,1.);
//
square.add(c1); square.add(c2);
square.add(c3); square.add(c4);
//
square.name="square";
square.element_type="c2d4";
square.elset_name="square";
square.mesh.name="square.geof";
//
square.make_connectivity();
square.link();
//
master("save_as square.mast");
}
please note the last instruction (master("save_as square.mast");
)…
master
is a global object which allows to pass string messages to
zMaster. The message “save_as toto.mast” asks zMaster to save the
current geometry in a file named ’toto.mast’.
You can run this script either using ’Zrun -B square.z7p’ (the script will be executed and a master file created), ’Zmaster square.z7p’ (the geometry will be created just after launch of zMaster), or using ’Run script’ option in ’Action’ menu.
\(\bullet\) how to mesh a parametric AE specimen…
//
// MASTERSCRIPT
// begin
// STRING name Specimen_name ae_specimen
// STRING eltype Element_type c2d8
// double height Specimen_height 10.
// double width Specimen_width 3.
// double depth Notch_depth 1.5
// double radius Notch_radius 1.5
// int n_left N_edges_left 10
// int n_right N_edges_right 8
// int n_top N_edges_top 5
// int n_bottom N_edges_bottom 5
// int n_arc N_edges_arc 5
// bool reduce Reduced_integration 0
// end
//
void main()
{
global double depth,radius,height,width;
double theta1,theta2;
double s;
global int n_left,n_right,n_top,n_bottom,n_arc;
int tot_edge;
global int reduce;
global string name,eltype;
PAVING specimen;
POINT A,C,D,F,G,H,G1,F1;
LINE l1,l2,l3,l4;
ARC a1;
LISET left,right,top,bottom,notch;
("Got the following values :"+endl).print();
("width="+width+endl).print();
("height="+height+endl).print();
("depth="+depth+endl).print();
("radius="+radius+endl).print();
endl.print();
//
A.x=0.; A.y=0.;
C.x=0.; C.y=height;
D.x=width; D.y=C.y;
H.x=radius+width-depth; H.y=0.;
G.x=width-depth; G.y=H.y;
if(G.x<=0.) ERROR("Invalid width/depth");
//
s=(width-H.x)/radius;
if((s>0.)|(s<-1.)) ERROR("Invalid radius");
theta1=acos((width-H.x)/radius);
theta2=pi;
F.x=width;
F.y=H.y+radius*sin(theta1);
//
tot_edge=n_top+n_bottom+n_left+n_right+n_arc;
if(tot_edge%2) {
("Odd number of edges detected. Adding one edge to top side."+endl).print();
n_top=n_top+1;
}
l1.bind(D,F); l2.bind(C,D); l3.bind(A,C); l4.bind(G,A);
l1.set_nodes(n_right,1.);
l2.set_nodes(n_top,1.);
l3.set_nodes(n_left,1.);
l4.set_nodes(n_bottom,1.);
a1.set_parameters(H,radius,theta1,theta2,F,G);
a1.set_nodes(n_arc,1.);
//
specimen.add(l1);
specimen.add(l2);
specimen.add(l3);
specimen.add(l4);
specimen.add(a1);
specimen.name=name;
specimen.elset_name=name;
specimen.element_type=eltype;
right.add(l1); right.name="right";
top.add(l2); top.name="top";
left.add(l3); left.name="left";
bottom.add(l4); bottom.name="bottom";
notch.add(a1); notch.name="notch";
//
specimen.remesh();
//
left.link(); right.link(); top.link(); bottom.link(); notch.link();
specimen.link();
//
master("save_as toto.mast");
specimen.mesh.name="toto.geof";
specimen.mesh.save();
}
\(\bullet\) A very complex example : how to mesh a ’real’ gear, using involute curves. This example makes an intensive use of many objects, and is thus very interesting to show the possibilities of the coupling between zMaster and zLanguage.
void do_involute(int direction, VECTOR vx, VECTOR vy, double re, double ri, int disc)
{
//
// Makes a involute curve
//
double theta,theta_max,t;
double l;
double a,b,c,delta;
double d1,d2,dt;
int i,nnode;
vx.resize(disc+1); vy.resize(!vx);
theta_max=1./ri*sqrt(re^2.-ri^2.);
("theta_max="+theta_max+endl).print();
l=.5*ri*theta_max^2./disc;
//
if(direction==1) { vx[0]=ri; vy[0]=0.; }
else { vx[!vx-1]=ri; vy[!vy-1]=0.; }
theta=0.;
for(i=0;i<!vx;i=i+1) {
if(direction==1) {
vx[i]=ri*(cos(theta)+theta*sin(theta));
vy[i]=ri*(sin(theta)-theta*cos(theta));
t=sqrt(2.*l/ri+theta*theta);
dt=t-theta;
theta=theta+dt;
} else if(direction==-1) {
vx[!vx-i-1]=ri*(cos(theta)+theta*sin(theta));
vy[!vy-i-1]=ri*(sin(theta)-theta*cos(theta));
t=-sqrt(2.*l/ri+theta*theta);
dt=t-theta;
theta=theta+dt;
} else ERROR("Unkown direction : "+direction);
}
}
void do_tooth_points(VECTOR r_vx, VECTOR r_vy, VECTOR l_vx, VECTOR l_vy,
double awidth, double re, double ri, int disc, double tm)
{
VECTOR p;
MATRIX rot;
double alpha;
int i,d;
//
do_involute(1,r_vx,r_vy,re,ri,disc);
tm=acos(r_vx[!r_vx-1]);
do_involute(-1,l_vx,l_vy,re,ri,disc);
//
alpha=(awidth-2*tm)/2.;
//
rot.set_rotation(-(tm+alpha));
p.resize(2);
for(i=0;i<!r_vx;i=i+1) {
p[0]=r_vx[i]; p[1]=r_vy[i];
p=rot*p;
r_vx[i]=p[0]; r_vy[i]=p[1];
}
//
rot.set_rotation(tm+alpha);
p.resize(2);
for(i=0;i<!l_vx;i=i+1) {
p[0]=l_vx[i]; p[1]=l_vy[i];
p=rot*p;
l_vx[i]=p[0]; l_vy[i]=p[1];
}
}
void do_tooth(double tm, double awidth, double re, double ri, int disc, double angle,
ARRAY<LINE> lines)
{
VECTOR r_vx,r_vy;
VECTOR l_vx,l_vy;
VECTOR p;
MATRIX rot;
int i,iline,jpoint;
ARRAY<POINT> points;
do_tooth_points(r_vx,r_vy,l_vx,l_vy,awidth,re,ri,disc,tm);
rot.set_rotation(angle);
p.resize(2);
for(i=0;i<!r_vx;i=i+1) {
p[0]=r_vx[i]; p[1]=r_vy[i];
p=rot*p;
r_vx[i]=p[0]; r_vy[i]=p[1];
}
for(i=0;i<!l_vx;i=i+1) {
p[0]=l_vx[i]; p[1]=l_vy[i];
p=rot*p;
l_vx[i]=p[0]; l_vy[i]=p[1];
}
//
lines.resize(2*(!l_vx-1));
points.resize(2*(!l_vx));
jpoint=0;
for(i=0;i<!r_vx;i=i+1) {
points[jpoint].x=r_vx[i];
points[jpoint].y=r_vy[i];
jpoint=jpoint+1;
}
for(i=0;i<!l_vx;i=i+1) {
points[jpoint].x=l_vx[i];
points[jpoint].y=l_vy[i];
jpoint=jpoint+1;
}
//
jpoint=0;
iline=0;
for(i=0;i<!r_vx-1;i=i+1) {
lines[iline].bind(points[jpoint+1],points[jpoint]);
iline=iline+1;
jpoint=jpoint+1;
}
jpoint=jpoint+1;
for(i=0;i<!l_vx-1;i=i+1) {
lines[iline].bind(points[jpoint+1],points[jpoint]);
iline=iline+1;
jpoint=jpoint+1;
}
}
void do_gear(DELAUNAY domain, LISET ext, int n_teeth, double awidth, double re, double ri,
int disc, int dea, int dia)
{
ARRAY< ARRAY<LINE> > all_lines;
ARRAY<ARC> arcs,other_arcs;
ARRAY<POINT> pts1,pts2,ppts1,ppts2;
double tm,wa,space,angle,alpha1,alpha2;
int i,itooth;
VECTOR p1,p2;
space=(2*pi-n_teeth*awidth)/n_teeth;
//
all_lines.resize(n_teeth);
other_arcs.resize(n_teeth);
arcs.resize(n_teeth);
pts1.resize(n_teeth);
pts2.resize(n_teeth);
ppts1.resize(n_teeth);
ppts2.resize(n_teeth);
//
for(itooth=0;itooth<n_teeth;itooth=itooth+1) {
("Tooth n. "+itooth+endl).print(); cflush();
angle=2*pi/n_teeth*(itooth+1);
do_tooth(tm,awidth,re,ri,disc,angle,all_lines[itooth]);
wa=(awidth-2*tm)/2.;
arcs[itooth].set_parameters(center,re,angle-wa,angle+wa,ppts1[itooth],ppts2[itooth]);
arcs[itooth].set_nodes(dea,1.);
}
//
for(itooth=0;itooth<n_teeth;itooth=itooth+1) {
("Arc n. "+itooth+endl).print(); cflush();
angle=2*pi/n_teeth*(itooth+1);
alpha1=awidth/2.+angle;
alpha2=alpha1+space;
other_arcs[itooth].set_parameters(center,ri,alpha1,alpha2,pts1[itooth],pts2[itooth]);
if(itooth==0) other_arcs[itooth].set_nodes(dia+1,1.);
else other_arcs[itooth].set_nodes(dia,1.);
}
//
domain.name="gear";
domain.elset_name="gear";
domain.element_type="c2d3";
domain.propagation=1;
//
for(itooth=0;itooth<n_teeth;itooth=itooth+1) {
for(i=0;i<!(all_lines[itooth])/2;i=i+1) domain.add(all_lines[itooth][i]);
for(i=0;i<!(all_lines[itooth])/2;i=i+1) ext.add(all_lines[itooth][i]);
domain.add(arcs[itooth]);
for(i=!(all_lines[itooth])/2;i<!all_lines[itooth];i=i+1) {
domain.add(all_lines[itooth][i]);
ext.add(all_lines[itooth][i]);
}
domain.add(other_arcs[itooth]);
}
domain.link();
// domain.make_connectivity();
}
void main()
{
global POINT center;
VECTOR px,py;
double r_int,r_ext;
global double ang_t;
int d_i_arc,d_e_arc,di,nteeth,i;
double awidth,rtrou;
int n_trou,neh;
DELAUNAY domain;
LISET internal,internal2,external;
ARRAY<POINT> pts_trou;
ARRAY<LINE> trou;
double angle;
r_ext=1.; r_int=.725;
nteeth=8; di=9; d_i_arc=2; d_e_arc=4;
awidth=pi/6.;
//
n_trou=5; rtrou=.15; neh=4;
//
center.x=0.; center.y=0.;
//
do_gear(domain,external,nteeth,awidth,r_ext,r_int,di,d_e_arc,d_i_arc);
//
pts_trou.resize(n_trou);
trou.resize(n_trou);
for(i=0;i<n_trou;i=i+1) {
pts_trou[i].x=center.x+rtrou*cos(2.*pi/n_trou*i+angle);
pts_trou[i].y=center.y+rtrou*sin(2.*pi/n_trou*i+angle);
}
for(i=0;i<n_trou-1;i=i+1)
trou[i].bind(pts_trou[n_trou-i-2],pts_trou[n_trou-i-1]);
trou[n_trou-1].bind(pts_trou[n_trou-1],pts_trou[0]);
for(i=0;i<!trou;i=i+1) {
trou[i].set_nodes(neh,1.);
}
for(i=0;i<!trou;i=i+1) domain.add(trou[i]);
for(i=0;i<!trou;i=i+1) internal.add(trou[i]);
for(i=0;i<!trou/2;i=i+1) internal2.add(trou[i]);
internal.name="internal"; internal2.name="internal2";
internal.elset_name="internal"; internal2.elset_name="internal2";
external.name="external";
external.elset_name="external";
domain.link(); internal.link(); internal2.link(); external.link();
}
