Вы находитесь на странице: 1из 116

MSC.

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

Asia Pacific Worldwide Web


MSC.Software Corporation www.mscsoftware.com
Entsuji-Gadelius Building
2-39, Akasaka 5-chome
Minato-ku, Tokyo 107-0052, JAPAN
Telephone: (81) (03) 3505-0266
Fax: (81) (03) 3505-0914

Document Title: MSC.Marc Python Tutorial, Version 2001


Part Number: MA*2001*Z*Z*Z*DC-TAU-PYT
Revision Date: April, 2001

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

■ Organization of this Manual

■ Contents of the Chapters

■ 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

Organization of this Manual


This manual is divided into three parts:
Part I introduces the user to the PyMentat module. This module interacts with
MSC.Marc Mentat (which will be referred to as Mentat) to create, modify, and post
process models.
Part II introduces the user to the PyPost module. This module functions
independently of Mentat to post process a Marc post file (results file). It is currently
only available on the DEC UNIX, Windows NT (Intel), SUN Solaris 2.6 or higher, HP
PA 2.x, and SGI platforms.
Part III introduces the user to more advanced uses of the PyMentat and PyPost
modules.

Contents of the Chapters


Chapter 1 Introduction, provides information on the basics using PyMentat and of
Python programming.

PART I PyMentat Module

Chapter 2 PyMentat: A Simple Example, describes a basic PyMentat script.


Chapter 3 PyMentat: Obtaining Data from Mentat, expands on the common
features of PyMentat and describes how a Python script can get data from
Mentat.
Chapter 4 PyMentat: Building Complex Geometry, displays how you can build
complex geometry that cannot be done with procedure files alone.
Chapter 5 PyMentat: Adding Model Properties, shows how to add boundary
conditions, material properties, geometric properties and job parameters
to allow you to perform a complete linear elastic analysis of a rectangular
strip with a series of holes subjected to compression loading.
Chapter 6 PyMentat: Processing a Post File, shows how to process a Marc post
file.
Chapter 7 PyMentat: Sets, shows how to write PyMentat scripts to work with
SETS.
PREFACE ix
Preface

PART II PyPost Module

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.

PART III Advanced Discussions

Chapter 11 PyMentat: Using the py_connect Method, introduces the basics of


using the PyMentat module in a client/server environment.
Chapter 12 PyPost: Plotting Post File Data, shows some example of using third
party modules to plot the results of a post file.
x MSC.Marc Python Tutorial

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

■ The Basics of Using PyPost

■ A Brief Look at Python Programming

Welcome to Python - a set of API’s designed to be used by Python scripts to enhance


the functionality of Mentat.
2 MSC.Marc Python Tutorial

The Basics of Using PyMentat


When you select a menu item in Mentat, it does one of two things:
1. You are presented with a new menu screen
2. A command is issued.
The concept of using the PyMentat module uses Item 2. To build or modify models
using the PyMentat module, a Python script sends a sequence of commands to Mentat.
These commands are the same commands that are issued when you select the
appropriate menu item.
For example, if you select the menus:

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

GENERATE TEST MODEL

RUN py_create.py USING mentat.proc is created


MENTAT.PROC TO CREATE when Mentat is run
INITIAL PYTHON SCRIPT

DEVELOP AND MODIFY Add new commands as


PYTHON SCRIPT needed in the script

TEST PYTHON SCRIPT

Figure 1-1 The Python Script Development Process

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

The Basics of Using PyPost


The PyPost module is used by a Python script to process a MARC post (results) file.
It operates independently from Mentat. The PyPost API provides a set of methods to
be used to obtain the scalar, tensor or vector values stored in a post file.

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

Table 1-1 (Continued)

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

A Brief Look at Python Programming


In order to enhance your understanding of using PyMentat or PyPost, we will
introduce you to the basics of programming with Python.
Python is an interpreted, interactive object-oriented programming language
sometimes compared to Perl, Java, and Tcl. It has interfaces to IP networking,
windowing systems, audio, and other technologies. Integrated with Mentat, it
provides a more powerful scripting language than procedure files since it contains
conditional logic and looping statements such as if, while and for.
A Python script that will use the PyMentat module needs to import the py_mentat
module using the following syntax:
from py_mentat import *
Similarly, a Python script that will use the PyPost module needs to import the py_post
module using the following syntax
from py_post import *
One of the biggest differences between the Python language and other programming
languages is that Python does not denote blocks of code with reserved words or
symbols such as if..then..endif (FORTRAN) or if { ... } (curly braces in C). Instead,
indenting is used for this purpose. For example, the take following block of
FORTRAN code:
if(jtype.eq.49) then
ladt=idt+lofr
endif
The block of FORTRAN code would need to be coded as follows in Python:
if jtype == 49:
ladt=idt+lofr
Python matches the amount of indenting to the block of code. The colon at the end of
the if statement denotes that it is a compound statement. All the lines that are to be in
that block of code need to be at the same indent level. The block of code is ended when
the indenting level returns to the level of to the compound statement. The examples in
the following chapters will show you more about the Python syntax.
8 MSC.Marc Python Tutorial

Python Data Types


When programming in Python you don’t explicitly declare a variable’s data type.
Python determines the "data type" by how the variable is used. Python supports the
following implied data types:
Basic Data Types
string
A character string similar to the char data in C and character in FORTRAN. a string
may be specified using either single or double quotes.
float
A floating point number similar to the double data type in C and the real*8 data type
in FORTRAN.
integer
An integer or fixed point number similar to the long int data type in C and the
integer*8 data type in FORTRAN.
Extended Data Types
List
A Python list is essentially a linked list that can be accessed like an array using the
square bracket operators "[ ]". The list can be composed of strings, floats or integers
to name a few.
The material covered in this tutorial is very basic and should be easy to access and
understand for the first time Python user. Once you have worked through the sample
sessions in Part II you should feel comfortable enough to do a complete analysis
simply by extrapolating from what you have learned in the example problems.
A multi-dimension list is created by first creating a single dimensional list and then
creating the other dimensions, as follows (a 3x2 array):
A = [None] * 3
for i in range(3)
A[i] = [None] * 2
CHAPTER
PyMentat: A Simple Example
2
■ Chapter Overview

■ Creating a Simple Python Script for Mentat

■ Python Programming Hints

■ Running the Script


2 MSC.Marc Python Tutorial

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

Creating a Simple Python Script for Mentat


To begin, we will examine a script that creates a simple element grid. This example is
named chap2.py and can be found in the Mentat directory examples/python/tutorial/
c02. Note that the first Python statement contains.
1 from py_mentat import *
This statement will import the PyMentat module into the Python script. It must be
used in all Python scripts that will need to access the PyMentat module.
The remaining code that creates the grid is as follows:
2 # Create the node grid
3 def make_nodes(s,t, xs, ys):
4 y= ys
5 z = 0.0
6 delx = 1.0/s
7 dely = 1.0/t
8 for i in range(0,t):
9 x = xs
10 for j in range(0,s):
11 str = "*add_nodes %f %f %f" % (x, y, z)
12 py_send(str)
13 x = x + delx
14 y = y + dely
15 return
16
17 # Create the element grid
18 def make_elements(n,m):
19 for i in range(1,m): # the "y" dir
20 n1 = (i-1) * (n) + 1
21 n2 = n1 + 1
22 n4 = n1 + (n)
23 n3 = n2 + (n)
24 for j in range(1,n): # the "x" dir
25 str = "*add_elements %d %d %d %d" %
(n1,n2,n3,n4)
26 py_send(str)
4 MSC.Marc Python Tutorial

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

Python Programming Hints


In this example, some Python functions (or routines) were created to build the grid. A
Python function is defined with the compound statement def. The syntax is:
def NAME ’(’ [args] ’)’ ’:’
What follows after the colon is the code that comprises the function. The lines of
Python code that define the function must be indented at least one space. To end the
function definition, the code is "deindented".
The range function is used quite often in these examples. When the range function is
used, Python builds a "list" of integers starting at the first value and ending at one less
than the last value. For example, the statement:
for i in range(0,5):
is actually executed as
for i in [0,1,2,3,4]:
In the Python script shown, a string is created and sent to Mentat using the py_send
routine. The string could also be built in the calling argument for py_send, as shown
below:
py_send("*add_nodes %f %f %f" % (x, y, z))
The command and the floating point values to be passed are specified in the calling
argument.
6 MSC.Marc Python Tutorial

Running the Script


Start Mentat, and from the main screen select the following menu buttons.

MAIN
UTILS
PYTHON

This will bring up the Python Menu screen as shown in Figure 2-1.

Figure 2-1 Python Menu Screen


CHAPTER 2 7
PyMentat: A Simple Example

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.

Figure 2-2 The Python Browser Window


8 MSC.Marc Python Tutorial

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.

Figure 2-3 Python Menu Screen with a Created Mesh

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

■ Creating a Simple Python Script for Mentat

■ The py_get_int and py_get_float methods

■ Running the Script


2 MSC.Marc Python Tutorial

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

Creating a Simple Python Script for Mentat


To continue with the example discussed in Chapter 2, we will examine a script that
creates a simple element grid and uses Mentat parameters to control the size of the
grid. This example is named chap3.py and can be found in the Mentat directory
examples/python/tutorial/c03. The script is as follows:
1 from py_mentat import *
2 # Create the node grid
3 def make_nodes(s, t, xs, ys):
4 y= ys
5 z = 0.0
6 delx = 1.0/s
7 dely = 1.0/t
8 for i in range(0,t):
9 x = xs
10 for j in range(0,s):
11 str = "*add_nodes %f %f %f" % (x, y, z)
12 py_send(str)
13 x = x + delx
14 y = y + dely
15 return
16
17 # Create the element grid
18 def make_elements(n,m):
19 for i in range(1,m): # the "y" dir
20 n1 = (i-1) * (n) + 1
21 n2 = n1 + 1
22 n4 = n1 + (n)
23 n3 = n2 + (n)
24 for j in range(1,n): # the "x" dir
25 str = "*add_elements %d %d %d %d"
(n1,n2,n3,n4)
26 py_send(str)
27 n1 = n1 + 1
28 n2 = n2 + 1
29 n3 = n3 + 1
4 MSC.Marc Python Tutorial

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.

Lines 41-44 If the script is invoked as a separate process, (such as "python


chap3.py"), then the Python interpreter sets the Python variable
__name__ to the string ’__main__’. If this is the case, then the Python
script should attempt to make a socket connection to Mentat. The
py_connect method will be discussed in more detail in a later chapter.
CHAPTER 3 5
PyMentat: Obtaining Data from Mentat

The py_get_int and py_get_float methods


The py_get_int and py_get_float methods provide access to Mentat PARAMETERS
and Arithmetic or Database functions. Using Mentat parameters is the method to
pass variables from Mentat to a PyMentat script. These variables are obtained
through PyMentat by specifying the name of the parameter or function in the string
passed to the py_get_int or py_get_float method. These parameters may be
combined with any of the Arithmetic or Database functions described in the
MSC.Marc Python Reference Manual.
When using the py_get_int or py_get_float methods, they must be used on a system
of the same byte architecture. The values are not converted to a machine independent
format before being transmitted.

Running the Script


First, start Mentat. Before running this example, some PARAMETERS need to be
defined. The values for these parameters will be obtained by the Python script to
control the size and the position of the grid.
Select the following menus:

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

■ Running the Script


2 MSC.Marc Python Tutorial

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

Figure 4-1 Plate with Varying Number of Holes


4 MSC.Marc Python Tutorial

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

33 for i in range(0, ny) :


34 y = ys + i * f
35 for j in range(0, nx) :
36 x = xs + j * f
37 py_send("%f %f 0 %f" % (x, y, r))
38 return 0
39
40 def main():
41 width = py_get_float("width")
42 height = py_get_float("height")
43 diameter = py_get_float("diameter")
44 spacing = py_get_float("spacing")
45 xstart = -width/2
46 ystart = -height/2
47 build_plate(xstart,ystart,width, height, diameter,
spacing)
48 return
49
50 if __name__ == ’__main__’:
51 py_connect("127.0.0.1",40007)
52 main()

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.

Lines 50-52 If run in a separate process, make a socket connection to Mentat.

Running the Script


Start Mentat and use the FILES menu SET DIRECTORY button to specify examples/
python/tutorial/c04 as the current directory. The parameters used in this model may
be specified with the USER DEFINED menu HOLES IN PLATE (Python). Enter the
following values for this example:

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.
.

Figure 4-2 Resulting Plate with Holes

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

■ Node and Element Id’s

■ Running the Script


■ Submitting the Job
2 MSC.Marc Python Tutorial

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

Figure 5-1 Plate with Varying Number of Holes

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

Node and Element Id’s


The Database functions use node and element id’s (similar to labels) as their
arguments. In the add_bc routine of our Python script we issue the renumber_all
command. This command will renumber all of the entities in the model. This ensures
that the index value passed to the database function node_x is the same as that of the
loop value. We need to do this because the entities (nodes in this case) are stored in
the database as a linked list as shown in Figure 5-2.

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

Figure 5-2 A Linked List of Nodes


CHAPTER 5 9
PyMentat: Adding Model Properties

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

Figure 5-3 A Linked List of Nodes with Node 2 Deleted

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

Running the Script


You may run the procedure file chap5.proc to set the parameters or you may specify
them using the UTIL submenu PARAMETERS as follows:

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

Figure 5-4 Resulting Mesh with Boundary Conditions Applied

Submitting the Job


You may run the job by using the following menus:

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

■ Running the Script


2 MSC.Marc Python Tutorial

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 21 The loop for all of the scalars in our 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 24-25 Specify the scalar name to use.

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 29-30 Obtain the node id for this node.

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.

Line 43 Turn off the legend

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 43 Start the *select_node command.


Lines 47-52 Print out the results for each scalar.

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".

Line 55 Turn on NUMERICS.

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.

Running the Script


This script runs the same way as in the previous examples. Bring up the Python
browser and browse to the Mentat directory examples/python/tutorial/c06 and run the
Python script chap6.py.
When the script completes, the output will appear as shown in Figure 6-1.
CHAPTER 6 7
PyMentat: Processing a Post File

Label node scalar


-------------------------------------------
Displacement x 53 0.00128282
Displacement y 49 0.00565143
External Force x 0 0
External Force y 50 187.5
Reaction Force x 82 2866.6
Reaction Force y 81 921.814

Figure 6-1 Resulting Output from chap6.py

Figure 6-2 Resulting Post Plot from chap6.py

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

■ Running the Script


■ Set Id’s and Set Names
2 MSC.Marc Python Tutorial

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 3-4 Open the model to examine the set information.

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 12 Obtain the number of entries in his set.

Line 14 Print the set header information.

Line 15 Loop through all the entries in this set.

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

Running the Script


To run this script, bring up the Python browser and browse to the Mentat directory
examples/python/tutorial/c07 and run the Python script chap7.py. However, do not
select the RUN AS SEPARATE PROCESS button since the Python console/terminal
window will exit when it is finished and the resulting print statements will not be seen.
When the script completes, the output will appear as shown in Figure 7-1.

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

Figure 7-1 Resulting Output from chap7.py


CHAPTER 7 7
PyMentat: Sets

Set Id’s and Set Names


In most cases, it is desirable to reference sets using their names. However, all of the
database functions for sets use the "set id". The following piece of Python code will
take a set name and search for the set id.

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

■ Running the Script


2 MSC.Marc Python Tutorial

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

15 for j in range(0, nns):


16 k= 0
17 numnodes = p.nodes()
18 while k < numnodes:
19 d = p.node_scalar(k,j)
20 if d < 0.0:
21 d = -d
22 if d > max_scalars[j] :
23 max_scalars[j] = d
24 max_nodes[j] = p.node_id(k)
25 k = k + 1
26
27 print " Label node scalar"
28 print " ---------------------------------------"
29
30 for i in range(0,nns):
31 str = " %18s %10i %g" %
(p.node_scalar_label(i),
max_nodes[i],max_scalars[i])
32 print str
33 return
34
35 if __name__ == ’__main__’:
36 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 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 7 Go to the first increment.


CHAPTER 8 5
PyPost: Reading a Post File

Line 8 This statement will call the node_scalars method to obtain the total
number of nodal scalars stored in the post file.

Lines 10-12 The lists are initialized.

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 15 This begins the main loop for the scalars.

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.

Lines 30-32 Print out the results for each scalar.


6 MSC.Marc Python Tutorial

Running the Script


This script is intended to be run outside of Mentat. In an X-terminal window or
Windows NT command prompt window, change your directory to the Mentat
directory examples/python/tutorial/c08. Run the Python script chap8.py as:
python chap8.py
When the script completes, the output will printed as shown in Figure 8-1.

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

Figure 8-1 Resulting Output from chap8.py

In the next chapter, we will begin working with element data.


CHAPTER
PyPost: Obtaining Element Data
9
■ Chapter Overview

■ Processing Element Data

■ Running the Script


2 MSC.Marc Python Tutorial

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

Processing Element Data


In the previous chapter, you saw how to use the Pypost module to process nodal data.
In this chapter, we will process element data.
Processing the element data is more complex since elements contain multiple nodes
and integration points. The values obtained at the nodes are obtained by extrapolating
the values at the integration points. There are 3 extrapolation methods available
through the extrapolation method:
linear Extrapolate by averaging the integration points to the centroid of the
element and then doing a linear extrapolation from the centroid
through the integration point to the node.
translate Do not extrapolate, but rather copy the data at each integration point
to its corresponding node. In those cases where there are fewer
integration points than nodes, some averaging of neighboring
integration points may be done.
average The average of all the integration points is computed and assigned to
the nodes. Therefore, all nodes have an equal value assigned to them.
Consider the quadrilateral element shown Figure 9-1.

4 7 3 4 7 3

3 4

8 6 8 6

1 2

1 5 2 1 5 2

Eight node quadrilateral Four Gaussian integration points


Node
Integration pt

Figure 9-1 Element Class 8: Eight Noded Isoparametric Quadrilateral Elements


4 MSC.Marc Python Tutorial

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.

Line 7 Go to the first increment.

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

Line 19 The outer loop is the one for the increments.

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 40 Begin the loop for the element scalars.

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 48 Loop over every node in the list.

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.

Lines 60-69 Print out the results for each scalar.


8 MSC.Marc Python Tutorial

Running the Script


This script is run similar to that of the previous chapter. In an X-terminal window or
Windows NT command prompt window, change your directory to the Mentat
directory examples/python/tutorial/c09. Run the Python script chap9.py as:
python chap9.py
When the script completes, the output will be appear as shown in Figure 9-2.

Increments = 26 , Nodal scalars = 9 , Element scalars 6

Item Label increment node scalar


---------------------------------------------------------------------------
1 Displacement x 240 1 0.829858
2 Displacement y 190 23 0.0844004
3 Displacement z 240 75 1.83052
4 External Force x 240 60 216.668
5 External Force y 240 66 357.812
6 External Force z 0 1 0
7 Reaction Force x 240 18 4017.09
8 Reaction Force y 220 98 111.656
9 Reaction Force z 240 18 1.24391
10 Equivalent Von Mises Stress Layer 1 240 52 106931
11 Equivalent Von Mises Stress Layer 3 240 83 77594.8
12 Equivalent Von Mises Stress Layer 5 240 25 103107
13 Equivalent Plastic Strain Layer 1 240 53 0.181767
14 Equivalent Plastic Strain Layer 3 240 84 0.0871299
15 Equivalent Plastic Strain Layer 5 240 25 0.211298

Figure 9-2 Resulting Output from chap8.py

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

■ Processing Element Tensor Data

■ Running the Script


2 MSC.Marc Python Tutorial

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

Processing Element Tensor Data


In the previous chapter, you saw how to use the PyPost module to process nodal and
element scalar data. In this chapter, we will process the element tensor data and use
the PyTensor data type.
This example is named chap10.py and can be found in the Mentat directory examples/
python/tutorial/c10. The Python code is as follows:
1 from py_post import *
2 import sys
3 class TensorData:
4 def __init__(self, v, n, i):
5 self.Value = v
6 self.Node = n
7 self.Inc = i
8
9 def set_data(self, v,n,i):
10 self.Value = v
11 self.Node = n
12 self.Inc = i
13
14 def increment(self):
15 return self.Inc
16
17 def value(self):
18 return self.Value
19
20 def node(self):
21 return self.Node
22
23 def get_tensors(fname):
24 p = post_open(fname)
25
26 max_values = []
27
28 p.moveto(1)
4 MSC.Marc Python Tutorial

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.

Line 28 Go to the first increment. This must be performed before we attempt to


get any data from the post file, such as the number of element scalars
available.

Lines 30-31 The number of element tensors and the number of increments in the post
file are obtained.

Line 43 Begin the increment loop.


6 MSC.Marc Python Tutorial

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.

Line 80 The filename is specified as the first argument to the script.

Running the Script


This script is run similar to that of the previous chapter. In an X-terminal window or
Windows NT command prompt window, change your directory to the Mentat
directory examples/python/tutorial/c10. Run the Python script chap10.py as:
python chap10.py chap10.t16
When the script completes, the output will appear shown in Figure 10-1.

Found 2 element tensors


12 increments
Scanning increment 1
Scanning increment 2
Scanning increment 3
Scanning increment 4
Scanning increment 5
Scanning increment 6
Scanning increment 7
Scanning increment 8
Scanning increment 9
Scanning increment 10
Scanning increment 11
Item Label increment node tensor
----------------------------------------------------------
1 Stress 4 15 58564.1
2 Plastic Strain 6 9 0.103661

Figure 10-1 Resulting Output from chap10.py


CHAPTER
PyMentat: Using the py_connect
11 Method

■ Chapter Overview

■ Creating a Simple Python Script for Mentat

■ The py_connect Method

■ Handling Socket Errors

■ Running the Script


2 MSC.Marc Python Tutorial

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

Creating a Simple Python Script for Mentat


We will use the Python script shown in Chapter 3 which will create a simple element
grid and use Mentat PARAMETERS to control the size of the grid. This example is
named chap3.py and can be found in the Mentat directory examples/python/tutorial/
c03. The code is shown completely in Chapter 3, however, what we are interested in
now is at lines 41-44 as follows:
41 if __name__ == ’__main__’:
42 py_connect("",40007)
43 main()
44 py_disconnect()
If the script is invoked as a separate process, (such as "python chap3.py"), then the
Python interpreter sets the Python variable __name__ to the string ’__main__’. If this
is the case, then the Python script should attempt to make a socket connection to
Mentat. The first argument to py_connect is the hostname, and if it is NULL it will
use the local host. The second argument is the port number.

The py_connect Method


The py_connect method provides a method in which a Python script performs a BSD
socket connection to Mentat to send commands and obtain parameters. It allows
Mentat to be fully interactive while the Python script is executing.
When the RUN command in the Python menu is selected, it will bring up the Python
browser window. An option in the Python browser window is RUN AS SEPARATE
PROCESS. If this is enabled, then Mentat will initiate a socket connection using the
command for the INITIATE CONNECTION menu item, and then the Python script is run
using the python interpreter (python.exe on Windows NT) program located in Mentat’s
bin directory. The Python script will need to complete the connection using a call to the
PyMentat method py_connect, specifying the hostname and the port number to be used.
The port number used in the Python script must be the same as specified in Mentat, and
may be changed by selecting the PORT button. The hostname may be blank (an empty
string), in which case the connection will be attempted on the local host.
All output from the Python script will appear in Mentat’s XTerm window on UNIX or
the Command Prompt window on Windows NT. When Python scripts ends it should
call the py_disconnect method to complete the termination of the socket connection.
4 MSC.Marc Python Tutorial

Handling Socket Errors


Sometimes a socket may become unusable and Mentat cannot make a connection to a
certain port. A port number may be described as "in use", even though it appears that
no Python script is running. You should check that no "zombie" Python process is
running in the background (using the ’ps’ command on UNIX or the Task Manager on
Windows NT). If a Python process is running and it has a connection to the port, it
must terminate before another process can make a connection to that port.
The error "Specified address in use" may occur in the following scenario on a UNIX
system:
1. Mentat is started and the INITIATE CONNECTION button is selected.
2. In a separate window, a Python script makes a successful socket connection
to Mentat.
3. Mentat exits before the Python script completes or calls the py_disconnect
method.
4. Mentat is started again, and the INITIATE CONNECTION button is selected.
The error "Specified address in use" may occur. To resolve the problem, use
a different port number or wait for the socket timeout to occur (about 4-5
minutes).
If all else fails, try using a different port number. You may also want to specify the port
number as an argument to the Python script. You may do this as shown in the
following code example:
1 import sys
2 if __name__ == ’__main__’:
3 port = 40007
4 if len(sys.argv) > 1:
5 port = sys.argv[1]
6 py_connect("",port)
7 main()
8 py_disconnect()
CHAPTER 11 5
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.

Figure 11-1 The Python Browser Window


6 MSC.Marc Python Tutorial

Running the Script


First, start Mentat. Before running this example, some PARAMETERS need to be
defined. The values for these parameters will be obtained by the Python script to
control the size and the position of the grid.
Select the following menus:

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

■ Charting Script for Mentat

■ The Gnuplot Module

■ The PyOpenGL Module


2 MSC.Marc Python Tutorial

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

Charting Script for Mentat


In this first example, we will use a simple charting module that creates a JPEG file.
We will use it here to create a plot of the Y displacements for 4 nodes. Note that this
module is somewhat limited since it does not support annotations and has no support
for legends. However, it can be useful for creating quick and simple plots. We will use
a post file which displays a simple contact example. This example is named
chap12a.py and can be found in the Mentat directory examples/python/tutorial/c12.
The output from this example is a JPEG file name chap12a.jpg.
The following is the Python code to use the gdchart module to create a JPEG plot.
1 from py_post import *
2 import gdchart
3 opt = gdchart.option
4
5 opt(set_color=(0xff8080, 0x8080ff, 0x80ff80))
6 opt(bg_color=0xaaaaaa, plot_color=0x0000cd,
line_color=0x000000)
7 size = (450, 450)
8
9 def do_plot(fname, t, Incs, dta):
10 opt(set_color=(0xff8080, 0x8080ff, 0x80ff80))
11 opt(bg_color=0xaaaaaa, plot_color=0x0000cd,
12 line_color=0x000000,format=gdchart.GDC_JPEG)
13 opt(title=t, xtitle=’Increment’, ytitle=’
Y-Displ’,grid=1)
14 f=open(fname,’wb’)
15 gdchart.chart(gdchart.GDC_LINE, size, f,
16 Incs, dta[0], dta[1], dta[2], dta[3])
17 f.close()
18
19 def main(fname):
20 p = post_open(fname)
21 p.moveto(1)
22 nns = p.node_scalars()
23 ninc = p.increments()
24 print " Increments = ",ninc
4 MSC.Marc Python Tutorial

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

58 do_plot("chapt12a.gif", title, Incs ,displacements)


59
60 if __name__ == ’__main__’:
61 main("../c09/chap9.t16")

Line 2 The chart module gdchart is imported.

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 35 Create a string array for the increments.

Line 38-41 Find the index to the displacements for the node scalars.

Line 43 Loop through all the increments.

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

Figure 12-1 The Resulting JPEG File from chap12a.py


CHAPTER 12 7
PyPost: Plotting

The Gnuplot Module


The gnuplot module interfaces with the Gnuplot program to create PostScript plots. It
does not create plots on its own. Instead, it communicates with the Gnuplot program
in much the same way as the PyMentat module communicates with Mentat. The
gnuplot module will send commands to the Gnuplot program, and plots will appear in
the Gnuplot window. This module is more robust than the gdchart module because it
supports annotations and provides much more control over the plot.
1 from py_post import *
2 import os
3
4 try:
5 # Check if the package has been installed correctly
6 import Gnuplot
7 except:
8 print "Gnuplot has not been installed"
9
10 def gnu_plot(fname, title, Incs, dta, check_nodes):
11 import time
12 g = Gnuplot.Gnuplot(debug=1)
13
14 g.title(title)
15 g(’set data style linespoints’)
16 g(’set size .6,.6’)
17 d = [None] * len(check_nodes)
18 for i in range(0,len(check_nodes)):
19 d[i] = Gnuplot.Data(Incs, dta[i], title="Node "
+ ‘check_nodes[i]‘, with=’lines ’ + ‘i+3‘+ ’
’ + ‘i+3‘)
20 g.xlabel(’Increments’)
21 g.ylabel(’Y-Displ’)
22 g.plot(d[0], d[1], d[2], d[3])
23 if os.name == "nt" :
24 raw_input(’Please press return to
continue...\n’)
25 else :
8 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.

Line 10 The gnu_plot routine is a convenient wrapper function to the plotting


routine Gnuplot in the gnuplot module.

Line 12 Create the Gnuplot object.

Lines 14-15 Set the title, the linestyle, and the size of the plot.

Line 16 Create an array to store the Gnuplot Data objects.

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 28 Create the postscript file.


10 MSC.Marc Python Tutorial

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.

Figure 12-2 The Resulting PostScript File from chap12b.py


CHAPTER 12 11
PyPost: Plotting

The PyOpenGL Module


The OpenGL module is an interface to the PyOpenGL API that can be used by Python
scripts to draw 3-D graphics. It is useful to create 3-D graphs, plots, or to display the
model itself which will be shown in this example. The original model and the final
displaced model will be displayed.
The post file model is a 2-D model from the Chapter 9 example. It requires the
PyOpenGL module and the Numeric extensions from LLNL.
1 from py_post import *
2 from Numeric import *
3 from OpenGL.GL import *
4 from OpenGL.Tk import *
5 from OpenGL.GLUT import *
6
7 # list of the nodes to label
8 check_nodes = [1,4,7,45]
9
10 class Displ:
11 def __init__(self, i, xv, yv, dxv, dyv):
12 self.Id = i
13 self.X = xv
14 self.Y = yv
15 self.dX = dxv
16 self.dY = dyv
17 def x(self):
18 return self.X
19 def y(self):
20 return self.Y
21 def dx(self):
22 return self.dX
23 def dy(self):
24 return self.dY
25 def id(self):
26 return self.Id
27
12 MSC.Marc Python Tutorial

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

62 BMfonts = ( "glut9by15", "glut8by13",


63 "glutTimesRoman10", "glutTimesRoman24",
64 "glutHelvetica10", "glutHelvetica12",
"glutHelvetica18" )
65
66 # draw a symbol for the node
67 def draw_dot(x,y):
68 dot = array([0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF,
69 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF])
70 glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
71
72 wid = 3
73 hei = 3
74 glRasterPos3f(x,y,0.0)
75 t=dot.tostring()
76 glDrawPixels(wid, hei, GL_RGBA, GL_UNSIGNED_BYTE, t)
77 return
78
79 def draw_string(str,x,y):
80 glRasterPos3f(x,y,0.0)
81 for i in range(len(str)):
82 glutBitmapCharacter("glut9by15", ord(str[i]));
83 return
84
85 def draw_element(i):
86 # draw the original shape
87 glColor3f(1,0,0)
88 glBegin(GL_LINE_STRIP)
89 glVertex2f(nodex[i], nodey[i])
90 glVertex2f(nodex[i+1], nodey[i+1])
91 glVertex2f(nodex[i+2], nodey[i+2])
92 glEnd()
93 # draw the deformed shape
94 glColor3f(0,1.0,0.0)
14 MSC.Marc Python Tutorial

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

130 glVertex2f(x2, y-.1)


131 glEnd()
132 draw_string("deformed",x2+.05, y-.1)
133 return
134
135 def redraw(o):
136 glClearColor(0.1, 0.1, 0.1, 0)
137 glColor3f(1,0,0)
138 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
139 mode_3d()
140
141 glDisable(GL_LIGHTING)
142 for i in range(0,len(nodex),3):
143 draw_element(i)
144 plot_nodes(check_nodes)
145 draw_legend()
146 glEnable(GL_LIGHTING)
147 return
148
149 def find_node(n,nod):
150 for i in range(0,len(nod)):
151 if nod[i].id() == n:
152 return i
153 return -1
154
155 def find_maxmin(x, y):
156 global maxx, maxy, minx, miny
157 if maxx < x : maxx = x
158 if maxy < y : maxy = y
159 if minx > x : minx = x
160 if miny > y : miny = y
161
162 def main(fname):
163 global nodex, nodey, nodedx, nodedy
164 global maxx, maxy, minx, miny
16 MSC.Marc Python Tutorial

165 global nod # List of Displ objects


166 global win
167 global o, p
168
169 p = post_open(fname)
170 p.moveto(1)
171 nns = p.node_scalars()
172
173 ninc = p.increments()
174 print " Increments = ",ninc
175
176 # find the index ih the scalar label list for the
displacements
177 for i in range(0,nns):
178 s = p.node_scalar_label(i)
179 if s == "Displacement X" :
180 nlocx = i
181 if s == "Displacement Y" :
182 nlocy = i
183
184 # go to the last increment
185 p.moveto(p.increments()-1)
186 k = 0
187
188 # get nodes
189 nod = [Displ] * p.nodes()
190 while k < n:
191 j = p.node_id(k)
192 i = k
193 np = p.node(k)
194 dx = p.node_scalar(k,nlocx)
195 dy = p.node_scalar(k,nlocy)
196 nod[k] = Displ(j,np.x, np.y,dx,dy)
197 k = k + 1
198
CHAPTER 12 17
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

232 miny = miny - .25*(maxy-miny)


233 maxy = maxy + .25*(maxy-miny)
234 win = Win(minx, maxx,miny, maxy, width(), height())
235
236 f = Frame()
237 f.pack(side=’top’,expand=1)
238 quit=Button(f,text = ’Quit’,command =
sys.exit).grid(row = 0, column = 0, sticky =W)
239
240 t = "Increments " + ‘p.increments()‘
241 lbl = Label(f, text=" ").grid(row=0, col=2,
sticky=W)
242 lbl = Label(f, text=t).grid(row=0, col=3, sticky=W)
243 o = Opengl(width = width(), height = height(),
double = 1)
244 o.redraw = redraw
245 o.pack(side = ’top’, expand = 1, fill = ’both’)
246 o.focus_set()
247 o.mainloop()
248
249 if __name__ == ’__main__’:
250 main("../c09/chap9.t16")
251

Line 2 Import the Numeric (NumPy) extension.

Lines 3-5 Import the OpenGL, OpenGL toolkit (Tkinter), and the OpenGL
GLUT modules.

Lines 10-26 Create a class for storing the displacement data.

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 163-167 Declare some global variables.

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

Line 215 Loop through all the elements.

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

Figure 12-3 The Resulting Plot from chap12c.py


22 MSC.Marc Python Tutorial

Вам также может понравиться