C reate a p3_user_menu.pat304.def file in your home directory that adds a pulldown menu to MSC.Patran called PAT304 that allows you to access all of the PCL programs that you have written in this class.
The p3_user_menu.pat304.def file should use the following lines:
-
*MENU LABEL = PAT304
-
*ALWAYS ENABLED = FALSE
-
*CLASS
-
*FUNCTION
-
*LABEL
-
*END FUNCTION
Optionally, you may include:
-
*CASCADE MENU
-
*CASCADE END
-
*SEPARATOR
Exercise 14: Toolbar
A dd a toolbar icon to MSC.Patran’s toolbar that lets you toggle between 2 views.
You will use the ga_view_aa_set(rot_x, rot_y, rot_z) function to define the views. This function sets the view by defining the absolute x, y, and z angles of rotation about the MSC.Patran global model axes. The variables, rot_x, etc. are in degrees.
You can define an icon if you like. However, MSC.Patran will use a default icon if you supply an icon filename that MSC.Patran cannot find in the p3toolbar.def file, i.e., this_does_not_exist.icon.
Basically, this exercise consists of:
-
Writing PCL code to toggle between 2 views (see next page).
-
Compile this code into your pat304.plb PCL library.
-
Create an icon (optional).
-
If the icon file is not in your home directory, you will need to create a p3midilog.pcl file that contains:
!!PATH /my/path/to/the/icons
-
Edit your p3toolbar.def file, adding lines for the definition of:
*ICON, *CLASS, *FUNCTION, *HELP, and *LOAD ITEM.
CLASS pat304_toolbar_view
CLASSWIDE LOGICAL flag /* flag will initially be FALSE */
FUNCTION toggle_view()
/* these represent rotations in degrees */
REAL rot_x, rot_y, rot_z
IF (flag) THEN
/* aircraft front view */
rot_x = -90.0
rot_y = 0.0
rot_z = 90.0
ELSE
/* aircraft rhs view */
rot_x = -90.0
rot_y = 0.0
rot_z = 180.0
END IF
/* echo this to the session file */
> ga_view_aa_set(rot_x, rot_y, rot_z)
flag = !flag
/* flag is remembered between calls because it is
a classwide variable */
END FUNCTION /* toggle_view */
END CLASS /* pat304_toolbar_view */
Some Final Thoughts -
Remember that there are exceptions to all rules and sometimes there are even exceptions to the exceptions.
-
Remember that PCL is not a compiled language (like C or FORTRAN) but is an interpretive language (like BASIC).
-
In real estate it is location, location, location. However, to increase the performance of your PCL it is minimize database hits, minimize database hits, minimize database hits. The best way to increase the performance of your PCL function is to minimize database hits. The best way to minimize database hits is to move db_get_xxxx() or db_create_yyyy() statements outside of loops. Instead of getting data or creating entities one at time, it is better to get data for all selected entities with one database call and hold the data in an array until needed. Likewise, if you are creating entities, it is generally better to gather data in arrays and then create the entities all at once instead of creating them one at a time.
-
Utilize the PCL built-in functions. These functions are written in C or FORTRAN and are fast. As an example, instead of calculating beam element length by hand (get beam element nodes, get nodal coordinates, calculate length), utilize the fem_geom_edge_length() function instead.
-
If all else fails, see rule (1).
Some Final Thoughts
FUNCTION good_function(num_bars, bar_ids, bar_len)
/* This function calculates the length of 2-noded bar elements. */
/* This function is perfectly acceptable but is not very efficient
from a PCL programming point of view because it accesses the
database 2*num_bars times (once for each bar to get the bar nodes
and then once for each bar to get the bar node coordinates). Note
that this function may actually access the same nodal coordinate
data many times if the bars all connect at the same node.*/
INTEGER i, j, status
INTEGER num_bars, bar_ids()
INTEGER elm_connect(1, 2)
INTEGER rcids(1), acids(1)
REAL bar_len()
REAL xyz(2, 3)
REAL sum
FOR (i = 1 to num_bars)
status = db_get_node_for_elems(1, 2, bar_ids(i:i), elm_connect)
IF (status != 0) THEN RETURN (status)
status = db_get_nodes(2, elm_connect(1, 1:2), rcids, acids, xyz)
IF (status != 0) THEN RETURN (status)
sum = 0.0
FOR (j = 1 to 3)
sum += (xyz(2, j) – xyz(1, j))**2
END FOR
IF (sum > 0.0) THEN
bar_len(i) = mth_sqrt(sum)
ELSE
bar_len(i) = 0.0
END IF
END FOR
RETURN (0)
END FUNCTION
Some Final Thoughts
FUNCTION better_function(num_bars, bar_ids, bar_len)
/* This function calculates the length of 2-noded bar elements. */
/* This function is better than the previous function because it
only accesses the database 2 times regardless of how many
bar elements are entered.*/
INTEGER i, j, p1, p2, status
INTEGER num_bars, bar_ids()
INTEGER elm_connect(VIRTUAL)
INTEGER num_nodes, node_ids(VIRTUAL)
INTEGER idum(VIRTUAL)
REAL bar_len()
REAL xyz(VIRTUAL)
REAL sum
sys_allocate_array(elm_connect, 1, num_bars, 1, 2)
status = db_get_node_for_elems(num_nodes, 2, bar_ids, elm_connect)
IF (status != 0) THEN RETURN (status)
sys_allocate_array(node_ids, 1, 2*num_bars)
sys_move_raw(elm_connect, node_ids)
mth_sort(node_ids, TRUE, num_nodes)
sys_reallocate_array(node_ids, 1, num_nodes)
sys_allocate_array(idum, 1, num_nodes)
sys_allocate_array(xyz, 1, num_nodes, 1, 3)
status = db_get_nodes(num_nodes, node_ids, idum, idum, xyz)
IF (status != 0) THEN RETURN (status)
FOR (i = 1 to num_bars)
p1 = mth_array_search(node_ids, elm_connect(i, 1), TRUE)
p2 = mth_array_search(node_ids, elm_connect(i, 2), TRUE)
sum = 0.0
FOR (j = 1 to 3)
sum += (xyz(p2, j) – xyz(p1, j))**2
END FOR
IF (sum > 0.0) THEN
bar_len(i) = mth_sqrt(sum)
ELSE
bar_len(i) = 0.0
END IF
END FOR
RETURN (0)
END FUNCTION
Share with your friends: |