Professional Documents
Culture Documents
Python Tutor PDF
Python Tutor PDF
Marc
Python Tutorial
Version 2001
•
•
Copyright 2001 MSC.Software Corporation
Printed in U. S. A.
This notice shall be marked on any reproduction of this data, in whole or in part.
Corporate Europe
MSC.Software Corporation MSC.Software Gmbh
2 MacArthur Place Am Moosfeld
South Coast Metro, CA 92707 81829 München, GERMANY
Telephone: (714) 540-8900 Telephone: (49) (89) 431 9870
FAX: (714) 784-4056 Fax: (49) (89) 436 1716
Proprietary Notice
MSC.Software Corporation reserves the right to make changes in specifications and other information contained in this document
without prior notice.
ALTHOUGH DUE CARE HAS BEEN TAKEN TO PRESENT ACCURATE INFORMATION, MSC.SOFTWARE
CORPORATION DISCLAIMS ALL WARRANTIES WITH RESPECT TO THE CONTENTS OF THIS DOCUMENT
(INCLUDING, WITHOUT LIMITATION, WARRANTIES OR MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE) EITHER EXPRESSED OR IMPLIED. MSC.SOFTWARE CORPORATION SHALL NOT BE LIABLE FOR
DAMAGES RESULTING FROM ANY ERROR CONTAINED HEREIN, INCLUDING, BUT NOT LIMITED TO, FOR ANY
SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF, OR IN CONNECTION WITH, THE USE
OF THIS DOCUMENT.
This software documentation set is copyrighted and all rights are reserved by MSC.Software Corporation. Usage of this
documentation is only allowed under the terms set forth in the MSC.Software Corporation License Agreement. Any reproduction
or distribution of this document, in whole or in part, without the prior written consent of MSC.Software Corporation is prohibited.
Trademarks
All products mentioned are the trademarks, service marks, or registered trademarks of their respective holders.
C O N T E N T S
MSC.Marc Python Tutorial
Preface
Preface ■ Organization of this Manual, viii
Contents ■ Contents of the Chapters, viii
❑ PART I PyMentat Module, viii
❑ PART II PyPost Module, ix
❑ PART III Advanced Discussions, ix
■ Documentation Conventions, x
Chapter 1
Introduction ■ The Basics of Using PyMentat, 2
■ The Basics of Using PyPost, 5
■ A Brief Look at Python Programming, 7
❑ Python Data Types, 8
Basic Data Types 8
Extended Data Types 8
Chapter 2
PyMentat: A Simple ■ Chapter Overview, 2
Example
■ Creating a Simple Python Script for Mentat, 3
■ Python Programming Hints, 5
■ Running the Script, 6
Chapter 3
PyMentat: Obtaining Data ■ Creating a Simple Python Script for Mentat, 3
from Mentat
■ The py_get_int and py_get_float methods, 5
■ Running the Script, 5
iv MSC.Marc Python Tutorial
Chapter 4
PyMentat: Building ■ Background Information, 3
Complex Geometry
■ Running the Script, 6
Chapter 5
PyMentat: Adding Model ■ Plate Properties, 3
Properties
■ Node and Element Id’s, 8
■ Running the Script, 10
■ Submitting the Job, 11
Chapter 6
PyMentat: Processing a ■ Postprocessing Basics, 3
Post File
■ Scalar Values, 6
■ Running the Script, 6
Chapter 7
PyMentat: Sets ■ Set Basics, 3
■ A Simple Example, 4
■ Running the Script, 6
■ Set Id’s and Set Names, 7
Chapter 8
PyPost: Reading a Post ■ PyPost Basics, 3
File
■ Running the Script, 6
Chapter 9
PyPost: Obtaining ■ Processing Element Data, 3
Element Data
■ Running the Script, 8
Chapter 10
PyPost: Element Tensor ■ Processing Element Tensor Data, 3
Data
■ Running the Script, 6
Contents v
Chapter 11
PyMentat: Using the ■ Creating a Simple Python Script for Mentat, 3
py_connect Method
■ The py_connect Method, 3
■ Handling Socket Errors, 4
■ Running the Script, 6
Chapter 12
PyPost: Plotting ■ Charting Script for Mentat, 3
■ The Gnuplot Module, 7
■ The PyOpenGL Module, 11
vi MSC.Marc Python Tutorial
PREFACE
Preface
■ Documentation Conventions
The purpose of this manual is to introduce the user to the MSC.Marc Python (Python)
modules. The tutorial covers the basics of the modules and helps the novice Python
user in becoming comfortable in programming with these modules through a number
of examples that display some typical uses of creating and processing a model in
various stages. This tutorial is not intended to be a Python programming manual. The
book Programming Python by Mark Lutz should be used for this purpose. This
manual does assume that the Python user is experienced in using MSC.Marc Mentat.
viii MSC.Marc Python Tutorial
Chapter 8 PyPost: Reading a Post File, introduces the basics of using the PyPost
module to obtain post file data and find the maximum scalar values.
Chapter 9 PyPost: Obtaining Element Data, shows how to obtain element scalar
data from a post file.
Chapter 10 PyPost: Element Tensor Data, expands on obtaining element data by
showing how to obtain element tensor data from a post file. It also
introduces the PyTensor class.
Documentation Conventions
Listed below are some font and syntax conventions that are used to make the
information in this manual easier to understand:
• Cross-references (Links) are highlighted in Blue.
• Names of buttons that appear on the Mentat screen are in UPPER CASE. The
command issued will appear in lower case, such as *add_nodes. Note that the
"*" always precedes the command name to instruct Mentat that a command is
being issued.
• Literal user input and program prompts are in courier font.
• Names of processors are indicated in BOLD UPPER CASE.
• A carriage return keystroke is indicated by <CR>.
• The left mouse button is indicated by <ML>.
• The middle mouse button is indicated by <MM>.
• The right mouse button is indicated by <MR>.
• The mouse cursor is indicated by < > .
• A filename implies a concatenation of pathname and filename. The pathname
may be omitted if the filename is in your current directory. You will note the
patnames are specified with the forward slash character "/", as in examples/
python/userguide. For those using Windows NT, you will need to substitute the
forward slashes with the backslash character "\".
CHAPTER
Introduction
1
■ The Basics of Using PyMentat
MAIN
MESH GENERATION
grid ON
nodes ADD
you will see that the command name of *add_nodes is issued in the dialogue area of
Mentat. Therefore, if you want your Python script to add a node, your script should
send the command *add_nodes to Mentat.
Unless you are a very experienced Mentat user, you will most likely develop your
PyMentat Python script using the technique outlined in Figure 1-1.
CHAPTER 1 3
Introduction
To aid in the development of converting the procedure files to Python scripts, the
Python script shown in Figure 1-2 can be used to generate the Python code for any
given Mentat procedure file. To use the script, run it as follows:
python py_create.py mentat.proc my_script.py
This script simply reads the procedure file and wraps a py_send command around it.
You will need to edit the resulting Python script to add PARAMETERS and other
variables for conditional processing.
4 MSC.Marc Python Tutorial
#!/usr/bin/python
import sys
import string
def main(fnamei, fnameo):
i = open(fnamei,"r")
o = open(fnameo,"w")
o.write("from py_mentat import *\n")
o.write("def main():\n")
for line in i.readlines():
s = string.strip(line)
if s == "":
continue
st = " py_send(\"%s \")\n" % s
o.write(st)
o.write("\n")
o.write("if __name__ == ’__main__’:\n")
o.write(" main()\n")
if __name__ == "__main__":
main(sys.argv[1],sys.argv[2])
Figure 1-2 A Python Script to Convert a Mentat Procedure File to a Python Script
CHAPTER 1 5
Introduction
Table 1-1
Function Description
close Closes a currently open post file and frees any allocated
memory.
dies Returns the number of dies in the post file.
domains Returns the number of domains stored in the post file.
element Returns the element data for a particular element.
elements Returns the number of elements in the current increment.
element_id Returns the id of a particular element.
element_scalar Returns a list of a particular element scalar data for a
particular element.
element_scalars Returns the number of element scalars available.
element_scalar_label Returns the name of a particular element scalar.
element_sequence Returns the index number of a particular element id.
element_tensor Returns a list of a particular element tensor for a particular
element.
element_tensors Returns the number of element tensors available.
element_tensor_label Returns the name of a particular element tensor.
element_vector Returns a list of a particular element vector data for a
particular element.
element_vectors Returns the number of element vectors available
element_vector_label Returns the name of a particular element vector.
extrapolation Sets the integration point extrapolation method.
increments Returns the number of increments available in the post file
moveto Move to a specified increment in the post file
6 MSC.Marc Python Tutorial
Function Description
node
nodes Returns the number of nodes for the current increment.
node_displacement Returns the nodal displacement values for a particular node.
node_displacements Returns a 1 if nodal displacements are present in the post file,
0 otherwise.
node_id Returns the id of a particular node
node_scalar Returns the value of a particular node scalar for a particular
node.
node_scalars Returns the number of node scalars available.
node_scalar_label Returns the name of a particular node scalar.
node_sequence Returns the index number of a particular node id
node_vector Returns the value of a particular node vector at a particular
node.
node_vectors Returns the number of node vectors available.
node_vector_label Returns the name of a particular node vector.
post_open Opens a post file and returns the PyPost object of it.
set Returns the data for a particular set.
sets Returns the number of sets in the post file.
title Returns the title of the post file.
CHAPTER 1 7
Introduction
Chapter Overview
In this section, it will be demonstrated how to create a basic Python script that sends
commands to Mentat. For this purpose, a rectangular grid of elements will be created.
Upon completion of this chapter, you should have a clearer understanding of the
following areas:
• The basics for a PyMentat script
• How a Python script communicates with Mentat
• Python Menu layout
CHAPTER 2 3
PyMentat: A Simple Example
27 n1 = n1 + 1
28 n2 = n2 + 1
29 n3 = n3 + 1
30 n4 = n4 + 1
31 return
32
33 def main():
34 n = 6
35 m = 8
36 xs = -1.0
37 ys = -1.0
38 make_nodes(n,m,xs,ys)
39 make_elements(n,m)
40 return
Lines 2-15 The make_nodes routine will create a grid of s x t nodes, starting in
the lower left hand corner at the point (xs, ys, 0.0). The function range
is a built-in Python function that builds a Python list of integers. Note
line 11: This is where the Mentat command string for adding a node is
composed. The *add_nodes command is placed in a Python string, along
with the x,y,z node coordinates. The statement uses Python’s %
operator. It is used on string objects, and works much like C’s sprintf
function. A “%f”, “%g”, or “%e” designates a floating point number,
and a “%d” designates an integer. The objects on the right of the
% symbol are paired with the conversion codes starting with the first
% code inside the quoted string. The py_send routine is called with the
string to send the command string to Mentat, at which time Mentat
will run the command string just as if it was typed in the Mentat
dialogue area.
Lines 18-31 The make_elements routine will perform the element connectivity of the
node grid using the Mentat command *add_elements. The loop
beginning in line 24 will build the elements moving across the node grid
in the X direction and up the grid in the Y direction.
Lines 33-40 The main routine will set the size of the grid and the starting position.
CHAPTER 2 5
PyMentat: A Simple Example
MAIN
UTILS
PYTHON
This will bring up the Python Menu screen as shown in Figure 2-1.
To run the script, select the RUN button. The other menu items in Figure 2-1 will be
discussed in a later chapter on sockets. When the RUN button is selected the browser
window as shown in Figure 2-2 will appear.
Note the button named RUN AS SEPARATE PROCESS. This will run the script in a
separate window and communicate to Mentat using a BSD socket connection. This
item will be discussed in a later chapter. In order to use this option, a Python script
would need to use the py_connect routine to complete the socket connection with
Mentat. This will be discussed in the next chapter. Do not select this option for this
example. Browse to the examples/python/c02 directory and select the file chap2.py.
Then select OK to run the script.
When the script completes, a mesh will be created as shown in Figure 2-3.
In the next chapter, we will modify the script to use Mentat PARAMETERS to create a
variably sized grid.
CHAPTER
PyMentat: Obtaining Data from
3 Mentat
■ Chapter Overview
Chapter Overview
In this chapter, it will be demonstrated how to use Mentat PARAMETERS in a Python
script using the PyMentat module. It will also be shown how to run a Python script as
a separate process. Upon completion of this chapter, you should have a clearer
understanding of the following areas:
• The py_get_int and py_get_float methods
CHAPTER 3 3
PyMentat: Obtaining Data from Mentat
30 n4 = n4 + 1
31 return
32
33 def main():
34 n = py_get_int("x_size")
35 m = py_get_int("y_size")
36 xs = py_get_float("x_start")
37 ys = py_get_float("y_start")
38 make_nodes(n,m,xs,ys)
39 make_elements(n,m)
40
41 if __name__ == ’__main__’:
42 py_connect("",40007)
43 main()
44 py_disconnect()
Lines 2-31 The make_nodes and make_elements routines are the same as in the
previous chapter.
Lines 33-39 The main routine will obtain the values for the size of the grid and the
starting point from Mentat using parameters. The py_get_int method
will evaluate a formula and return an integer (fixed point) result similar
to the *calculator command. The py_get_float method will evaluate a
formula and return a floating point number. In this case these methods
obtain the values for these parameters.
MAIN
UTILS
PARAMETERS
NEW PARAMETER
x_size
10
y_size
8
x_start
-1.0
y_start
-1.0
Remember to press the carriage <CR> after typing in each of the numbers to create the
parameters. The procedure file chap3.proc may be executed to perform the above
commands for you if you wish.
6 MSC.Marc Python Tutorial
You may also type the *define command in Mentat’s command prompt window to
create or edit the parameter. For example, to create the parameter x_size you would
type
*define x_size 10
As in the previous chapter, bring up the Python browser window with the menus:
MAIN
UTILS
PYTHON
RUN
When the script completes, a mesh will be created the same as in the previous chapter.
CHAPTER
PyMentat: Building Complex
4 Geometry
■ Chapter Overview
■ Background Information
Chapter Overview
In this chapter, it will be demonstrated how to build more complex geometry using
Python. To continue with the example discussed in Chapter 3, we will examine a script
that creates a more complex model. This example uses Mentat’s User Defined menu
to present a simple menu for controlling the model’s properties.
Upon completion of this chapter, you should have a clearer understanding of the
following areas:
• Adding points, curves, and lines
• Become more familiar with Python programming
CHAPTER 4 3
PyMentat: Building Complex Geometry
Background Information
A rectangular plate of user defined width and height contains a varying number of
holes of user defined diameter d, equally spaced by a user defined distance s. It is
desired that the Python script determine how many holes can be placed in the plate,
and center the array of holes in the plate with the distance from any edge to the nearest
hole to be at least the distance s.
d d d
t=.75
height
d d d
s
d d d
width
This example is named chap4.py and can be found in the Mentat directory examples/
python/tutorial/c04. The following is the Python script:
1 from py_mentat import *
2 def add_plate(xs,ys,width, height):
3 py_send("*set_curve_type line")
4 py_send("*add_points")
5 py_send("%f %f 0" % (xs, ys))
6 py_send("%f %f 0" % (xs+width, ys))
7 py_send("%f %f 0" % (xs+width, ys+height))
8 py_send("%f %f 0" % (xs, ys+height))
9 py_send("*set_curve_type line")
10 py_send("*add_curves")
11 py_send("1 2")
12 py_send("2 3")
13 py_send("3 4")
14 py_send("4 1")
15 py_send("*fill_view")
16 return
17
18 def build_plate(xstart,ystart,width, height, diameter,
spacing):
19 f = diameter+spacing
20 nx = int((width-spacing)/f)
21 ny = int((height-spacing)/f)
22 if (nx < 1 or ny < 1 ):
23 print "Holes are too big!"
24 return 1
25 print "creating hole grid of ",nx, " by ",ny
26
27 add_plate(xs,ys,width,height)
28 xs = .5 * (width - f * (nx - 1)) + xstart
29 ys = .5 * (height - f * (ny - 1)) + ystart
30 py_send("*set_curve_type circle_cr")
31 py_send("*add_curves")
32 r = diameter / 2
CHAPTER 4 5
PyMentat: Building Complex Geometry
Lines 2-16 The add_plate routine will create the plate using 4 connected curves. It
first generates the end points of the curve using the *add_points
command and then creates the curves by connecting the points with the
*add_curves commands. In line 15, the *fill_view command is issued to
center and fill the plate properly on the screen.
Lines 18-38 The build_plate routine will calculate the number of holes that can be
placed in the plate and create them in their proper position. The variables
nx and ny in lines 20 and 21 are the number of holes to be placed in the
x and y direction, respectively. The Python int function is used to force
the values to be an integer. Once it has been determined that the plate is
big enough to contain at least one hole, the add_plate routine is called
in line 27 to create the plate itself. The initial x and y position for the first
hole is calculated in lines 28-29. The loop in lines 38-44 controls the
6 MSC.Marc Python Tutorial
vertical (height) placement, and the inner loop in lines 35-37 controls the
horizontal (width) placement.
Lines 40-48 The main routine will obtain the values for the size of the plate, the
diameter of the holes, and the spacing between holes from Mentat. The
lower left corner of the plate is calculated in lines 45-46 so that the plate
has its center at (0,0). The build_plate routine is then called to create the
geometry.
WIDTH
12.0
HEIGHT
8.0
DIAMETER
.75
SPACING
0.4
MESH SIZE
0.2
Remember to press the carriage return <CR> after typing in the numbers. Note that the
MESH SIZE parameter is not used in this example. When you specify these values,
the menu creates these parameters in Mentat, and the values for these parameters will
be obtained by the Python script to control the number of holes in the plate. Select the
BUILD button to create the model.
CHAPTER 4 7
PyMentat: Building Complex Geometry
When the script completes, a plate will be created as shown in Figure 4-2.
.
In the next chapter, we will mesh the plate and add the geometric and material
properties, boundary conditions, and job parameters.
8 MSC.Marc Python Tutorial
CHAPTER
PyMentat: Adding Model Properties
5
■ Chapter Overview
■ Plate Properties
Chapter Overview
In this chapter, it will be demonstrated how to add properties to the geometry create
in the previous chapter.
Upon completion of this chapter, you should have a clearer understanding of the
following areas:
• Using the Database functions
• Node and Element id’s
CHAPTER 5 3
PyMentat: Adding Model Properties
Plate Properties
As shown in the previous chapter, a rectangular plate of user defined width and height
contains a varying number of holes of user defined diameter d, equally spaced by a
distance s specified by the user. The array of holes will be centered in the plate, with
the distance from any edge to the nearest hole to be at least the distance s.
Y
1000 Lb/in2
d d d
t=.75
height
fixed d d d
d d d
width
In this chapter, we will update the Python script to apply the properties described in
Figure 5-1 to the plate. The material behavior is linear elastic with Young’s modulus
E = 30e6 and Poisson’s ratio ν = 0.3. A compression load with magnitude p = 1000
Lb/in2 will be applied to the top of the plate.
4 MSC.Marc Python Tutorial
This example is named chap5.py and can be found in the Mentat directory examples/
python/tutorial/c05. The following Python code has been added to the code shown in
the previous chapter:
79 # check if f1 == f2 within tolerance of tol
80 def check_tol(f1, f2, tol):
81 if f1 == f2:
82 return 1
83 if f1 + tol < f2:
84 if f1 - tol > f2:
85 return 1
86 return 0
87
88 def mesh_plate(width, height, diameter, spacing):
89 py_send("*set_curve_div_type_fix_avgl")
90 l = spacing/2.0
91 py_send("*set_curve_div_avgl %f" % l)
92 py_send("*apply_curve_divisions all_existing")
93 py_send("*dt_planar_trimesh all_existing")
94 return
95
96 def add_bc(xs,ys,width,height):
97 py_send("*renumber_all")
98 n = py_get_int("nnodes()")
99 # add fixed bc at left edge
100 py_send("*apply_type fixed_displacement")
101 py_send("*apply_dof x")
102 py_send("*apply_dof y")
103 py_send("*apply_dof z")
104
105 node_list = []
106 for i in range(1,n+1):
107 str = "node_x(%d)" % i
108 f = py_get_float(str)
109 if check_tol(f, xs, .001):
110 node_list.append(i)
CHAPTER 5 5
PyMentat: Adding Model Properties
111
112 py_send("*add_apply_nodes ")
113 for i in range(0,len(node_list)):
114 str = "%d " % node_list[i]
115 py_send(str)
116 py_send(" # ")
117 # add edge load at top
118 py_send("*new_apply")
119 py_send("*apply_type edge_load")
120 py_send("*apply_value p 1000.0 ")
121 py_send("*add_apply_curves 3 #")
122 return
123
124 def add_matl():
125 py_send("*material_type mechanical:isotropic")
126 py_send("*material_value isotropic:youngs_modulus
3e7 .3")
127 py_send("*add_material_elements all_existing")
128 return
129
130 def add_job():
131 py_send("*loadcase_type static")
132 py_send("*job_class mechanical")
133 py_send("*job_option dimen:pstress")
134 py_send("*add_post_tensor stress")
135 py_send("*add_post_var von_mises")
136 py_send("*element_type 6 all_existing")
137 py_send("*element_type 6 all_existing")
138 return
139
140 def add_geom_prop():
141 py_send("*geometry_type mech_planar_pstress ")
142 py_send("*geometry_value thick .75")
143 py_send("*add_geometry_elements all_existing")
144 return
6 MSC.Marc Python Tutorial
145
146 def main():
147 xs = 0.0
148 ys = 0.0
149 width = py_get_float("width")
150 height = py_get_float("height")
151 diameter = py_get_float("diameter")
152 spacing = py_get_float("spacing")
153 build_plate(xs,ys,width, height, diameter, spacing)
154 mesh_plate(width, height, diameter, spacing)
155 add_bc(xs,ys,width, height)
156 add_matl()
157 add_geom_prop()
158 add_job()
159 py_send("save_as_model chap5.mfd yes")
160 return
161
162 if __name__ == ’__main__’:
163 py_connect("",40007)
164 main()
165 py_disconnect()
166
Lines 2-8 The check_tol routine is a convenience function to compare two floating
point number for equality within a certain tolerance.
Lines 10-17 The mesh_plate routine will generate a 2-D planar Delaunay triangle
mesh. To generate the curve divisions, the spacing between the holes is
used to control the average length of the segments.
Lines 19-46 The add_bc routine will create the boundary conditions for the plate.
The left edge of the plate is fixed, and the top edge of the plate has an
edge load. We first obtain the number of nodes using the Database
function nnodes in line 3. In line 11, we renumber all the nodes in the
database so that the node index is the same as the node id. This will be
discussed more in detail later in this chapter. We set the displacement
type to be fixed in lines 6-12. The code in lines 14-20 will search through
CHAPTER 5 7
PyMentat: Adding Model Properties
the entire node list looking for a node that lies on the left edge of the
plate by examining it’s position in the X direction. If a match is found,
we obtain the node id (which may be different from it’s index position
in the database) and store that in our node_list. In lines 21-25, the
command *add_apply_nodes is used to apply the fixed boundary
conditions. We loop through the node_list and send the id’s, and then "#"
symbol to signal the "End List" command. Lines 28-31 is where the top
edge load is created. Here we simply apply the load to the curve at the
top of the plate (curve number 3).
Lines 48-52 The add_matl routine will apply the material properties to all the
elements of the plate.
Lines 54-61 The add_job routine will create the necessary job parameters.
Lines 63-67 The add_geom_prop routine will apply the necessary geometric
properties.
Lines 69-83 The main routine is similar to that of Chapter 4, however, the additional
routines are called to add the boundary conditions, the material
properties, the geometric properties and the job parameters.
8 MSC.Marc Python Tutorial
x = -1.0
y = -1.0
z = 0.0
id = 1
x = 1.0
y = -1.0
z = 0.0
id = 2
x = 1.0
y = 1.0
z = 0.0
id = 3
x = -1.0
y = 1.0
z = 0.0
id = 4
The linked list of nodes in Figure 5-2 shows a square grid of nodes 1,2,3,4. If node 2
is deleted, then the list would become 1,3,4 as shown in Figure 5-3.
x = -1.0
y = -1.0
z = 0.0
id = 1
x = 1.0
y = 1.0
z = 0.0
id = 3
x = -1.0
y = 1.0
z = 0.0
id = 4
If the database function node_id is now called with the value of 2, it will return 3, since
the second item in the list is node 3. If the command renumber_all is issued, then the
nodes will be renumbered to the sequence 1,2,3 and node_id(2) will return 2.
If we did not issue the renumber_all command, then the code sequence in lines 20-24
would need to be:
for i in range(1,n+1):
str = "node_id(%d)" % i
j = py_get_int(str)
str = "node_x(%d)" % j
f = py_get_float(str)
if check_tol(f, xs, .001):
node_list.append(j)
We want to avoid using the node_id function as much as possible because it needs to
search the entire database to find the node.
10 MSC.Marc Python Tutorial
UTIL
PARAMETERS
NEW PARAMETER
WIDTH
8.0
HEIGHT
4.0
DIAMETER
1.0
SPACING
0.5
Remember to press the carriage return <CR> after typing in each of the numbers.
Select the BUILD button to create the model.
When the script completes, a mesh will be created as shown in Figure 5-4.
CHAPTER 5 11
PyMentat: Adding Model Properties
MAIN
JOBS
RUN
SUBMIT 1
In the next chapter, we will examine postprocessing using the PyMentat module.
12 MSC.Marc Python Tutorial
CHAPTER
PyMentat: Processing a Post File
6
■ Chapter Overview
■ Postprocessing Basics
■ Scalar Values
Chapter Overview
In this chapter, it will be demonstrated how to use the Postprocessing commands of
Mentat in a Python script. This example will use the post file of the example created
in the previous chapter.
Upon completion of this chapter, you should have a clearer understanding of the
following areas:
• The basics of using PyMentat for Postprocessing
• How write an efficent PyMentat postprocessing PyMentat script.
• Selecting nodes for display
CHAPTER 6 3
PyMentat: Processing a Post File
Postprocessing Basics
PyMentat may also be used to post process a post file.
In this example, we will obtain all of the nodal scalar values on the post file generated
by running the example in the previous chapter.
This example is named chap6.py and can be found in the Mentat directory examples/
python/tutorial/c06. The following is the Python code:
1 from py_mentat import *
2
3 def main():
4 py_send("*post_close")
5 py_send("*post_open chap6_job1.t16")
6 py_send("*post_next")
7 py_send("*fill_view")
8 py_send("*post_contour_lines")
9
10 n = py_get_int("nnodes()") # get number of nodes
11 label = []
12 label.append("*post_value Displacement x")
13 label.append("*post_value Displacement y")
14 label.append("*post_value External Force x")
15 label.append("*post_value External Force y")
16 label.append("*post_value Reaction Force x")
17 label.append("*post_value Reaction Force y")
18
19 max_scalars = []
20 max_nodes = []
21 for i in range(0,6):
22 max_scalars.append(0.0)
23 max_nodes.append(0)
24 str = "*post_value " + label[i]
25 py_send(str)
26
27 j = 1
28 while j <= n:
4 MSC.Marc Python Tutorial
29 str = "node_id(%d)" % j
30 n_id = py_get_int(str)
31 str = "post_node_extra(%d)" % n_id
32 flag = py_get_int(str)
33 if flag == 0: # check for valid post node
34 str = "scalar_1(%d)" % n_id
35 f = py_get_float(str)
36 if f < 0.0:
37 f = -f
38 if f > max_scalars[i]
39 max_scalars[i] = f
40 max_nodes[i] = n_id
41 j = j + 1
42
43 py_send("*draw_legend off")
44 py_send("*unpost_nodes all_existing")
45 py_send("*post_nodes ")
46
47 print " Label node scalar"
48 print " ------------------------------------------"
49 for i in range(0,nns):
50 j = max_nodes[i]
51 str = " %18s %10i %g" % (label[i],
p.py_node_id(j),max_scalars[i])
52 print str
53 py_send( max_nodes[i] )
54 py_send(" #")
55 py_send("*post_numerics")
56 return
57
58 if __name__ == ’__main__’:
59 py_connect(’’,40007)
60 main()
61 py_disconnect()
CHAPTER 6 5
PyMentat: Processing a Post File
Lines 4-7 These statements open the post file and setup some options. We need to
do a *post_next in line 6 so that we are at "increment 0" in Marc
terminology.
Line 8 We need to tell Mentat that we are working with scalar values, so one of
the SCALAR PLOT commands need to be sent.
Line 10 This statement will get the number of nodes in the model. Note that this
number may change at different increments due to rezoning.
Lines 11-17 A Python list is used to store the names of the nodal scalars that are in
the post file. This is a convenient way of storing the names for use later.
A Python list has an append method, and it is used to add the desired
string to the list. Note that a Python list can be a list of anything, integers,
floating points values, Python dictionaries or other lists.
Lines 19-20 The max_scalars and max_nodes variables are declared as Python Lists.
The index of the list will be each of the scalars in the post file. The
maximum scalar value will be stored in the max_scalars list. The node
associated with the max_scalar value will be stored in the max_nodes
list.
Lines 22-23 We append initial values to our list. Remember that max_scalars and
max_nodes are linked lists, so we must have the item added to the list
before we access it.
Lines 28 Loop through all the nodes. Note that we use a while loop for this. We
had been using the Python range function, however, for the range
function Python builds a list of all the values in the range. If we had
100,000 nodes, Python would build a list with that many items.
Lines 31-32 Not all nodes in the post file are visible nodes. Some are nodes used
explicitly by Marc to perform special functions and are considered
"extra" nodes. The Database function post_node_extra will return 0 if a
6 MSC.Marc Python Tutorial
node is not an extra node, 1 if it is. This check is required to verify that
the values obtained are true post file values at a node.
Lines 33-34 Obtain the scalar value using the Database function scalar_1.
Lines 35-36 We will use only positive values. If it is negative, then change it to
positive.
Lines 37-39 Check the current value against the highest value in our list.
Lines 44-45 We need to remove all nodes from the post nodes list and then start the
*post_nodes selection. Note that once the *post_nodes selection process
has begun, we cannot call any of the py_get routines.
Line 53 Send this node as one of the nodes to select. Note that we use the Python
backquote operator which converts an integer for a float into a string.
Line 54 Send the "#" symbol to signify "End of List".
Scalar Values
Using the PyMentat module for postprocessing is somewhat complex: you have to
know what the scalar labels are, check for valid nodes, etc. The PyPost module avoids
this by providing methods to obtain what these items are.
In the next chapter, we will examine the post file using the Python module PyPost.
8 MSC.Marc Python Tutorial
CHAPTER
PyMentat: Sets
7
■ Chapter Overview
■ Set Basics
■ A Simple Example
Chapter Overview
In this chapter, it will be demonstrated how to use sets in a Python script. This example
will use a simple model containing various sets.
Upon completion of this chapter, you should have a clearer understanding of the
following areas:
• The basics of sets in Mentat
• How to query set information in a Python script.
CHAPTER 7 3
PyMentat: Sets
Set Basics
Sets help to group items together to make it easier to reference them later. The
PyMentat module supports the following set types:
• node The set contains the node id’s of its entries.
• element The set contains the element id’s of its entries.
• point The set contains the point id’s of its entries.
• curve The set contains the curve id’s of its entries.
• surface The set contains the surface id’s of its entries.
• edge The set contains the element id’s and the edge number of its entries.
• face The set contains the element id’s and the face number of its entries.
Database functions have been added to Mentat to support sets. The list of functions
may be found in the MSC.Marc Python Reference Manual.
A Mentat model may contain any number of sets. The database function nsets is used
to obtain the number of sets in a model. Sets are referenced by its set id. The set id is
obtained using the database function set_id, which takes an index number as its only
argument. The remaining set functions use the set id to refer to the set, however,
Mentat refers to sets by name. The set name is obtained using the set_name function,
and the set type is obtained using the set_type function.
Each set in turn may contain multiple entries. The number of entries can be obtained
using the function nset_entries. The values for the entries are obtained using the
set_entry function, which returns a single value. If the set type is an edge set or a face
set, the second value, the edge, or face number is obtained by calling the set_edge or
set_face function, respectively.
4 MSC.Marc Python Tutorial
A Simple Example
In this example, we will obtain all of the set information in a simple Mentat model.
This example is named chap7.py and can be found in the Mentat directory examples/
python/tutorial/c07. The following is the Python code:
1 from py_mentat import *
2 def main():
3 py_send("*new_model yes")
4 py_send("*open_model sets.mfd")
5
6 m = py_get_int("nsets()")
7 print "Found ",m," sets"
8 for i in range(1,m+1):
9 id = py_get_int("set_id(%d)" % i)
10 sn = py_get_string("set_name(%d)" % id)
11 st = py_get_string("set_type(%d)" % id)
12 n = py_get_int("nset_entries(%d)" % id)
13
14 print "Set ",sn,"is a ",stype," set with ",n,"
entries"
15 for j in range(1,n+1):
16 k = py_get_int("set_entry(%d,%d)" %
(id, j))
17 print " entry ",j," is ",k,
18 if (stype == ’face’):
19 l = py_get_int("set_edge(%d,%d)" %
(id, j))
20 print " face number ",l
21 elif(stype == ’edge’):
22 l = py_get_int("set_edge(%d,%d)" %
(id, j))
23 print " edge number ",l
24 else:
25 print " "
26 return
CHAPTER 7 5
PyMentat: Sets
27
28 if __name__ == ’__main__’:
29 py_connect(’’,40007)
30 main()
31 py_disconnect()
Lines 6-7 Obtain and print the number of sets found. This uses the nsets Database
function.
Line 8 Loop through all the sets in the model. The sets begin at 1.
Line 9 Obtain the set id. All of the set database functions will use the "Set Id"
to locate the set information.
Line 10 Obtain the set name using the set_name database function.
Line 11 Obtain the set type using the set_type database function.
Line 16 Using the set_entry database function, obtain each item, and print out
the results.
Line 18-25 Depending on the set type, obtain the edge number or the face number
if it is an edge or face set.
6 MSC.Marc Python Tutorial
Found 8 sets
Set TOP is a node set with 2 entries
entry 1 is 3
entry 2 is 4
Set BOTTOM is a node set with 2 entries
entry 1 is 1
entry 2 is 2
Set LITTLE_EL is a element set with 1 entries
entry 1 is 2
Set RIGHT_ELEMENT is a element set with 1 entries
entry 1 is 3
Set RULED_SURF is a surface set with 1 entries
entry 1 is 1
Set BEZIER_CURVE is a curve set with 2 entries
entry 1 is 1
entry 2 is 2
Set EDGES is a edge set with 4 entries
entry 1 is 1 edge number 2
entry 2 is 2 edge number 1
entry 3 is 3 edge number 1
entry 4 is 3 edge number 2
Set FACES is a face set with 2 entries
entry 1 is 4 face number 0
entry 2 is 2 face number 0
def find_set_id(name):
n = py_get_int("nsets()")
for i in range(1,n+1):
id = py_get_int("set_id(%d)" % i)
sname = py_get_string("set_name(%d)" %
id)
if( sname == name):
return id
return -1
Figure 7-2 Python Code to Find the Set ID of a Given Set Name
8 MSC.Marc Python Tutorial
CHAPTER
PyPost: Reading a Post File
8
■ Chapter Overview
■ PyPost Basics
Chapter Overview
In this chapter, it will be demonstrated the basics of using PyPost to read a Marc post
file. This example will use the post file of the example created in the previous chapter.
Upon completion of this chapter, you should have a clearer understanding of the
following areas:
• The basics of using PyPost
• How to use PyPost to read nodal data
CHAPTER 8 3
PyPost: Reading a Post File
PyPost Basics
In the previous chapter, you saw how to use PyMentat to post process a post file.
The PyMentat module depends on interacting with Mentat. Sometimes it is more
convenient to work in a non-GUI environment, such as an X-Term window or a
Windows NT command prompt window. The PyPost module works in this manner.
PyPost is an API used in a Python script to obtain the results from a Marc post file.
The PyPost module contains one routine that is used to open a post file, post_open.
This routine returns a PyPost object. This PyPost object contains the methods that are
used to access various data items in the post file.
When using the PyPost module, you will import the module in the same way as
importing the PyMentat module, using the statement:
from py_post import *
To begin accessing a post file, you must call the PyPost routine post_open, such as:
pObj = post_open("chap5_job1.t16")
This statement opens the post file named chap5_job1.t16 and returns a PyPost object,
storing it in the variable pObj.
This example is named chap8.py and can be found in the Mentat directory examples/
python/tutorial/c08. The following Python code obtains the nodal scalar values from
the post file used in the previous chapter:
1 from py_post import *
2 def main(fname):
3 p = post_open(fname)
4 max_scalars = []
5 max_nodes = []
6
7 p.moveto(1)
8 nns = p.node_scalars()
9 print "Found ", nns, " node scalars "
10 for i in range(0,nns):
11 max_scalars.append(-1.0e20)
12 max_nodes.append(0)
13
14 # find maximum nodal scalars
4 MSC.Marc Python Tutorial
Line 3 The post_open routine is called with the post file name chap5_job1.t16.
It returns the PyPost object that is stored in the variable p. All
subsequent PyPost methods called will be members of this PyPost
object.
Lines 4-5 The max_scalars and max_nodes variables are declared as Python Lists.
The index of the list will be each of the scalars in the post file. The
maximum scalar value will be stored in the max_scalars list. The node
associated with the max_scalar value will be stored in the max_nodes
list.
Line 8 This statement will call the node_scalars method to obtain the total
number of nodal scalars stored in the post file.
Line 12 We call the moveto method to go to the first increment. When the post
file is opened it is at increment 0. Increment 0 contains only the model
data. We need to explicitly go to the first increment even though there is
only one increment of data in the post file.
Line 17 Obtain the number of nodes. If this post file had multiple increments, we
would have to call the nodes method every increment, since rezoning
will change the number of nodes.
Line 18 Loop through all the nodes. Note that we use a while loop for this. We
had been using the range function, however, Python builds a list of all
the values in the range for this function. If we had 100,000 nodes,
Python would build a list that large.
Line 19 Get the scalar value for this scalar (k) and node (j).
Lines 20-21 Ignore the sign of the values and only work with magnitudes.
Lines 22-24 Check the current value against the current maximum value. Convert the
node sequence number to the node id using the node_id method.
Found 6
node scalars
Label node scalar
-------------------------------------------
Displacement x 53 0.00128282
Displacement y 49 0.00565143
External Force x 1 0
External Force y 50 187.5
Reaction Force x 82 2866.6
Reaction Force y 81 921.814
Chapter Overview
In this chapter, it will be demonstrated how to obtain element data from a post file.
This example will use the post file of that created in Chapter 6.
Upon completion of this chapter you should have a clearer understanding of the
following areas:
• Obtaining the element data from a post file
• The element extrapolation methods available
CHAPTER 9 3
PyPost: Obtaining Element Data
4 7 3 4 7 3
3 4
8 6 8 6
1 2
1 5 2 1 5 2
The quadrilateral element of Figure 9-1 contains 8 nodes and 4 integration points. For
this element the PyPost method of element_scalar will return a list of eight nodes and
eight scalar values. If the extrapolation method is average, all eight nodes will have
the same value. If the extrapolation method is translate, then node 5 would be
calculated by averaging integration points 1 and 2. If the integration method is linear,
then all four integration points are averaged together and computed for the centroid of
the element. The values for the nodes are linearly extrapolated from the centroid to
their position on the element.
This example is named chap8.py and can be found in the Mentat directory examples/
python/tutorial/c08. The following is the Python code:
1 from py_post import *
2 def main(fname):
3 p = post_open(fname)
4 max_scalars = []
5 max_nodes = []
6 max_incs = []
7 p.moveto(1)
8 nns = p.node_scalars()
9 nes = p.element_scalars()
10
11 ninc = p.increments()
12 print " Increments = ",ninc,", Nodal scalars =
",nns, ", Element scalars ",nes
13
14 for i in range(0,nns+nes):
15 max_scalars.append(-1.0)
16 max_nodes.append(0)
17 max_incs.append(0)
18
19 for i in range(1, ninc):
20 p.moveto(i)
21 print "scanning increment ",i," post file
number ",p.increment
22
23 # find maximum nodal scalars
CHAPTER 9 5
PyPost: Obtaining Element Data
24 j = 0
25 while j < nns:
26 k = 0
27 numnodes = p.nodes()
28 while k < numnodes:
29 d = p.node_scalar(k,j)
30 if d < 0.0:
31 d = -d
32 if d > max_scalars[j] :
33 max_scalars[j] = d
34 max_nodes[j] = p.node_id(k)
35 max_incs[j] = p.increment
36 k = k + 1
37 j = j + 1
38
39 # find maximum element scalars
40 j = 0
41 while j < nes:
42 k = 0
43 numelems = p.elements()
44 while k < numelems:
45 sca = p.element_scalar(k,j)
46 l = len(sca)
47 m = 0
48 while m < l :
49 val = sca[m]
50 if val < 0.0:
51 val = -val
52 if val > max_scalars[nns+j] :
53 max_scalars[nns+j] = val
54 max_nodes[nns+j] = nod[m]
55 max_incs[nns+j] = p.increment
56 m = m + 1
57 k = k + 1
58 j = j + 1
6 MSC.Marc Python Tutorial
59
60 print " Item Label increment node scalar"
61 print " ------------------------------------------"
62
63 for i in range(0,nns+nes):
64 if i < nns:
65 s = p.node_scalar_label(i)
66 else:
67 s = p.element_scalar_label(i-nns)
68 str = "%7i %36s %7i %10i %g" % ((i+1),s,
max_incs[i], max_nodes[i],max_scalars[i])
69 print str
70
71 return
72
73 if __name__ == ’__main__’:
74 main("../c06/chap5_job1.t16")
Line 3 The post_open routine is called with the post file name chap5_job1.t16.
It returns the PyPost object that is stored in the variable p. All
subsequent PyPost calls will be members of this PyPost object.
Lines 4-6 The max_scalars, max_nodes, and max_incs variables are declared as
Python Lists. The index of the list will be each of the scalars in the post
file. The maximum scalar value will be stored in the max_scalars list.
The node associated with the max_scalar value will be stored in the
max_nodes list and the associated increment will be stored in the
max_incs list.
Lines 8-9 The node_scalars method is called to obtain the total number of nodal
scalars and the element_scalars method is called to obtain the total
number of element scales stored in the post file.
Lines 14-17 The lists are initialized. Note that the lists contain both the nodal and
element scalar data.
CHAPTER 9 7
PyPost: Obtaining Element Data
Lines 20-21 We call the moveto method with the current index number to step
through the increments. Remember that the index number passed in the
moveto method is not the same number as that which appears in the post
file. In line 21, we print out the current index number, and the increment
number as it appears in the post file.
Lines 24-37 This is the nodal scalars section, which is the same as that of the previous
chapter.
Lines 43-44 Obtain the number of elements in the current increment. Rezoning may
cause the number of elements to change between increments. Loop
through all the elements.
Line 45 Obtain the element scalars. The element_scalar method will return a list
of PyScalar values. A PyScalar has two members: an id and a value. The
id represents the node id, and value represents the scalar value.
Line 49 The PyScalar list returned is "read-only". This means that the values in
the list cannot be changed.
Lines 50-55 Check each value in the PyScalar list and compare them to the maximum
values.
In the next chapter, we will write a simple script to find the stresses greater than a
given value.
CHAPTER
PyPost: Element Tensor Data
10
■ Chapter Overview
Chapter Overview
In this chapter, it will be demonstrated how to use the PyPost module to examine the
element tensors. This example will use the post file of that created in Chapter 6.
Upon completion of this chapter, you should have a clearer understanding of the
following areas:
• Obtaining the element tensors
• Working with elements tensor data in a Python script
CHAPTER 10 3
PyPost: Element Tensor Data
29
30 net = p.element_tensors()
31 ninc = p.increments()
32 print "Found ", net, " element tensors "
33 print ninc, " increments "
34
35 if net == 0 :
36 print "Did not find element tensors"
37 return
38
39 for i in range(0,net):
40 max_values.append(TensorData(0.0, 0, 0))
41
42 i = 1
43 while i < ninc:
44 print "Scanning increment ",i
45 p.moveto(i)
46
47 j = 0
48 while j < net:
49 k = 0
50 num = p.elements()
51 while k < num:
52 el = p.element_tensor(k,j)
53 l = len(el)
54 m = 0
55 while m < l :
56 d = el[m].intensity
57 if d > max_values[j].value() :
58 max_values[j].set_data
(d, el[m].id, i)
59 m = m + 1
60 k = k + 1
61 j = j + 1
62
CHAPTER 10 5
PyPost: Element Tensor Data
63 i = i + 1 # next increment
64
65 print " Item Label increment node tensor"
66 print " ------------------------------------------"
67
68 for i in range(0,net):
69 j = max_value[i].node()
70 s = p.element_tensor_label(i)
71 str = "%7i %16s %7i %10i %g" % ((i+1),s,
max_values[i].increment(), j,
max_values[i].value())
72 print str
73 return 1
74
75 def main(fname):
76 get_tensors(fname)
77 return
78
79 if __name__ == ’__main__’:
80 main(sys.argv[1])
Line 2 The system module sys is imported to provide access to the command
line arguments.
Lines 3-21 A Python class is created to hold and retrieve the data.
Line 24 The post_open routine is called with the post file name passed in as the
first command line argument.
Lines 30-31 The number of element tensors and the number of increments in the post
file are obtained.
Line 50 Obtain the number of elements in this increment. Rezoning may cause
the number of elements to change between increments.
Lines 52-53 Obtain the list of PyTensors, and find the length of the list.
Lines 55-58 For each item in the list, compare it to the maximum value. The set_data
method of the TensorData class is used to set the values.
Lines 68-72 Print the results. In line 69, the node method of the TensorData class is
called to obtain the node id.
■ Chapter Overview
Chapter Overview
In this chapter, it will be demonstrated how to use Mentat PARAMETERS in a Python
script using the PyMentat module. It will also be shown how to run a Python script as
a separate process. Upon completion of this chapter, you should have a clearer
understanding of the following areas:
• The py_connect method
• Handling socket errors
Note that the use of the module in a separate process is currently available on the DEC
UNIX, Windows NT (Intel) SUN Solaris 2.6 or higher, HP PA 2.x, and SGI platforms.
CHAPTER 11 3
PyMentat: Using the py_connect Method
The sys module is used to obtain the "command line arguments", which contains the
Python list attribute named argv. The first item in the argv list in the name of the script
being run, and is therefore sys.argv[0]. If the length of this list is greater than 1, then
extra arguments were passed to the Python script. In this example, you would run the
script on the command line as:
python chap3.py 40008
The script would use the port number of 40008 and attempt to make the socket
connection with Mentat. The script could also be run using the Python browser
window, shown in Figure 11-1. In this case, the RUN AS SEPARATE PROCESS button
would be selected, and you would also specify the port number in the CALL
ARGUMENTS text box.
MAIN
UTILS
PARAMETERS
NEW PARAMETER
x_size
10
y_size
8
x_start
-1.0
y_start
-1.0
Remember to press the carriage <CR> after typing in each of the numbers to create the
parameters. The procedure file chap3.proc may be executed to perform the above
commands for you if you wish.
You may also type the *define command in Mentat’s command prompt window to
create or edit the parameter. For example, to create the parameter x_size you would
type
*define x_size 10
As in the previous chapter, bring up the Python browser window with the menus:
MAIN
UTILS
PYTHON
RUN
When the script completes, a mesh will be created the same as in Chapter 3.
CHAPTER
PyPost: Plotting
12
■ Chapter Overview
Chapter Overview
In this chapter, it will be demonstrated how to use third party Python modules in a
Python script to plot the results from a post file. Three examples of plotting will be
shown:
• Using the gdchart module to create a GIF plot
• Using the gnuplot module to create charts with Gnuplot.
• Using the OpenGL module to display 3-D models with PyOpenGL.
The examples shown here were developed only for Windows NT. See the readme.txt
file in the mentat2001/examples/python/tutorial\c12 directory for information
regarding what needs to be installed to run these examples.
CHAPTER 12 3
PyPost: Plotting
25
26 # The list of nodes to plot
27 check_nodes = (42, 66, 78, 86)
28
29 # Create an array for the displacements of
30 # the nodes in the list
31 displacements = [None]*len(check_nodes)
32 for i in range(0,len(check_nodes)):
33 displacements[i] = [0.0] * ninc
34
35 Incs = [’ ’] * ninc
36
37 nlocy = 0
38 for i in range(0,nns):
39 s = p.node_scalar_label(i)
40 if s == "Displacement Y" :
41 nlocy = i
42
43 for i in range(1, ninc):
44 p.moveto(i)
45 print "scanning post file increment
",p.increment
46 Incs[i] = ‘p.increment‘
47
48 # get the Y displacements for specified nodes
49 for k in range(0,len(check_nodes)):
50 j = p.node_sequence(check_nodes[k])
51 displacements[k][i] = p.node_scalar
(j,nlocy)
52
53 title = "Nodes "
54 for k in range(0,len(check_nodes)-1):
55 title = title + ‘check_nodes[k]‘ + ","
56 title = title + ‘check_nodes[len(check_nodes)-1]‘
57
CHAPTER 12 5
PyPost: Plotting
Lines 9-17 The do_plot routine is a convenient wrapper function to the plotting
routine chart in the gdchart module. We pass in the filename for the
plot, the title, and the X and Y values to plot.
Line 27 Create the list of nodes id’s to plot.
Lines 31-33 Create a two-dimensional array for the displacements. The list is the
size [number of nodes to plot] x [number of increments].
Line 38-41 Find the index to the displacements for the node scalars.
Lines 49-51 Loop over the list of nodes to plot. Use the node_sequence routine to
get the sequence number for the id’s in the check_nodes list.
Lines 53-56 Create the title for the plot. It will contain the list of the nodes used in
the plot.
In this example, you would run the script on the command line as:
python chap12a.py
The output from the script is shown in Figure 12-1.
6 MSC.Marc Python Tutorial
26 time.sleep(5)
27
28 g.hardcopy(fname, color=1) # enhanced = 1
29 print ’**** Saved plot to postscript file "%s"
****\n’ % fname
30 time.sleep(1)
31 return
32
33 def main(fname):
34 p = post_open(fname)
35
36 p.moveto(1)
37 nns = p.node_scalars()
38 ninc = p.increments()
39 print " Increments = ",ninc
40
41 check_nodes = (42,66,78, 86)
42 displacements = [None]*len(check_nodes)
43 for i in range(0,len(check_nodes)):
44 displacements[i] = [0.0] * ninc
45
46 Incs = [0] * ninc
47 nlocy = 0
48
49 # find the index for the displacements
50 for i in range(0,nns):
51 s = p.node_scalar_label(i)
52 if s == "Displacement Y" :
53 nlocy = i
54
55 for i in range(1, ninc):
56 p.moveto(i)
57 print "scanning post file increment
",p.increment
58 Incs[i] = p.increment
CHAPTER 12 9
PyPost: Plotting
59
60 # find all y displacements for specified nodes
61 for k in range(len(check_nodes)):
62 j = p.node_sequence(check_nodes[k])
63 dy = p.node_scalar(j,nlocy) # k
64 displacements[k][i] = dy
65
66 gnu_plot("chap12b.ps", "Node Displacements", Incs,
displacements, check_nodes)
67
68 if __name__ == ’__main__’:
69 main("chap12.t16")
Lines 4-8 Use the try/except statement to trap an error if the module gnuplot is
not available.
Lines 14-15 Set the title, the linestyle, and the size of the plot.
Line 18-19 Loop through each node in the ccheck_nodes list and create a title
containing the node number and set the line color to a different color
for each line.
Lines 20-21 Set the x and y axis labels.
Line 22 Call the plot routine to generate the plot. When the plot routine is
called, the data is sent to the gnuplot program and the plot is displayed.
Line 23-26 If the platform is Windows NT, pause the display. Otherwise wait for
5 seconds and then exit.
Line 30 Sleep (or pause) the program. If this is not done, a file will not be
generated.
Lines 33-66 The main routine is similar to that of the chap12a.py example.
When the script completes, a plot as shown in Figure 12-2 will be displayed in the
Gnuplot program, and will be saved as a PostScript plot in the file chap12b.ps.
28 class Win:
29 def __init__(self, left, right, bottom, top, w, h):
30 self.Left = left
31 self.Right = right
32 self.Bottom = bottom
33 self.Top = top
34 self.Width = w
35 self.Height = h
36 def left(self):
37 return self.Left
38 def right(self):
39 return self.Right
40 def bottom(self):
41 return self.Bottom
42 def top(self):
43 return self.Top
44 def width(self):
45 return self.Width
46 def height(self):
47 return self.Height
48
49 def width():
50 return 400
51
52 def height():
53 return 400
54
55 def mode_3d():
56 global win
57 glMatrixMode(GL_PROJECTION)
58 glLoadIdentity()
59 glOrtho(win.left(), win.right(), win.bottom(),
win.top(), -1.0,1.0)
60 glMatrixMode(GL_MODELVIEW)
61
CHAPTER 12 13
PyPost: Plotting
95 glBegin(GL_LINE_STRIP)
96 glVertex2f(nodedx[i], nodedy[i])
97 glVertex2f(nodedx[i+1], nodedy[i+1])
98 glVertex2f(nodedx[i+2], nodedy[i+2])
99 glEnd()
100 return
101
102 def plot_nodes(lst):
103 global p
104 glColor3f(1,1,1)
105 for i in range(len(lst)):
106 j = p.node_sequence(lst[i])
107 k=lst[i]
108 draw_string(‘k‘,nod[j].x(), nod[j].y())
109 draw_dot(nod[j].x(), nod[j].y())
110 dx = nod[j].x()+nod[j].dx()
111 dy = nod[j].y()+nod[j].dy()
112 draw_string(‘k‘,dx, dy)
113 draw_dot(dx,dy)
114 return
115
116 def draw_legend():
117 global win
118 glColor3f(1,0,0)
119 glBegin(GL_LINE_STRIP)
120 x1 = win.left() + .1
121 x2 = x1 + (win.right()-win.left())/5.0
122 y = win.bottom() +.15
123 glVertex2f(x1, y)
124 glVertex2f(x2, y)
125 glEnd()
126 draw_string("undeformed", x2+.05, y)
127 glColor3f(0,1.0,0.0)
128 glBegin(GL_LINE_STRIP)
129 glVertex2f(x1, y-.1)
CHAPTER 12 15
PyPost: Plotting
199 k = 0
200 n = p.elements()
201
202 # Create the x and y coordinate arrays for plotting.
203 # We should check the element list to find out how many
204 # nodes are in each element.
205 # We know for this model all elements have 3 nodes.
206 nodex = [0.0]*(n*3)
207 nodey = [0.0]*(n*3)
208 nodedx = [0.0]*(n*3)
209 nodedy = [0.0]*(n*3)
210 maxx = maxy = -10000.0
211 minx = miny = 10000.0
212
213 cnt=0
214 # build the x and y coordinate arrays
215 while k < p.elements():
216 el = p.element(k)
217 for m in range(0,el.len):
218 id=find_node(el.items[m],nod)
219 if id >=0 :
220 nodex[cnt] = nod[id].x()
221 nodey[cnt] = nod[id].y()
222 nodedx[cnt] = nod[id].x() +
nod[id].dx()
223 nodedy[cnt] = nod[id].y() +
nod[id].dy()
224 find_maxmin(nodex[cnt], nodey[cnt])
225 find_maxmin(nodedx[cnt], nodedy[cnt])
226 cnt = cnt+1
227 k = k +1
228
229 # Generate the Win object containing the viewport info
230 minx = minx - .25*(maxx-minx)
231 maxx = maxx + .25*(maxx-minx)
18 MSC.Marc Python Tutorial
Lines 3-5 Import the OpenGL, OpenGL toolkit (Tkinter), and the OpenGL
GLUT modules.
Lines 28-47 Create a class for storing information about the window.
Lines 49-53 The width and height function to return the desired size. Change the
values here to change the size of the window.
Lines 55-60 The mode_3d routine will set the OpenGL parameters for a 3-D
window.
CHAPTER 12 19
PyPost: Plotting
Lines 62-64 The BMfonts list contains the available fonts for displaying in the 3-D
window.
Lines 66-77 The drawdot routine will draw a 3x3 block of pixels. This is used to
identify the nodes we wish to see labelled.
Lines 79-83 The draw_string routine will draw a string of characters at the
specified position in the 3-D window
Lines 85-100 The draw_element routine will draw both the deformed and the
undeformed elements.
Lines 102-114 The plot_nodes routine will draw the "dot" to represent the node
location and will label the node for both the deformed and undeformed
elements.
Lines 116-133 The draw_legend routine will draw a legend in the lower left corner
reflecting the color of the lines used for the deformed and undeformed
shape.
Lines 135-147 The redraw routine is called by the Tkinter toolkit (which is registered
at line 247) to redraw the window. It calls the mode_3d routine to setup
the 3-D window, and then draws the elements, plots the nodes, and
draws the legend. If the window is resized or receives an expose event,
the toolkit will call this routine.
Lines 149-153 The find_node routine will find the index of a node id in the nod array.
Lines 155-160 The find_maxmin routine will find the maximum and minimum x and
y values in the model. This is used to determine the values to specify
when creating the 3-D window.
Lines 176-182 Determine the index of the X and Y displacements in the post file.
Lines 188-197 Create an array of Displ objects to store the displacement data. Loop
over all of the nodes and create an object.
Lines 206-209 Create the arrays to store the actual x and y coordinates to plot.
20 MSC.Marc Python Tutorial
Lines 217-226 For each node in the element, get the index of the node in the nod array
and store the data in the undeformed x and y arrays (nodex and nodey),
and also in the deformed x and y arrays (nodedx and nodedy). The
find_maxmin routine is called to find the maximum and minimum
values so that the window may be scaled appropriately.
Lines 229-234 Find the minimum and maximum values for the data so that the
window can be created with the proper limits.
Lines 236-237 Create the window frame using the Tkinter toolkit.
Lines 238-242 Create a quit button and a label that specifies the number of
increments.
Lines 243-247 Create the OpenGL object and specify the width, height and whether
double buffering is needed. Specify the redraw routine (line 244) and
get the window focus. Then start the main loop event processing
(line 247).
CHAPTER 12 21
PyPost: Plotting