
Using Internal NairnFEAMPM Script Control
Any text editing window for writing input commands (see NairnFEAMPM Commands) can alternatively be used to edit scripting commands to control and analyze calculations. The scripting commands use the same interpretive language commands used when creating input commands for calculations, but replaces the NairnFEAMPM commands for calculations with new commands for script control. The help topics for internal scripting control of NairnFEAMPM are:
- Creating and Running a Script
- Script Variables and Script Objects
- A Sample Internal Script
- Internal Scripting Commands
Creating and Running a Script
To create a script to control NairnFEAMPM, you can use the menu command New→Blank File. Scripts are plain text documents with interpretive language commands and the first scripting command must always be a Script
command. This command is how NairnFEAMPM distinguishes script control files from input command files used to set up FEA and MPM calculations.
Before a script can be run, the new document must be saved (with extension .fmcmd
). To run a script, use the "Interpret Commands" menu command (in the "Analyze" menu) or click the "interpret" icon in the tool bar (plain hammer icon). The script will run. The script may write results to it's console as calculations proceed. When the script is done, the script window will return to the front and any written results will be visible.
Script Variables and Script Objects
Scripts allow standard numeric and string variables supported by the interpretive language. In addition to these standard "variables", scripts define "objects," that represent things like commands documents, results documents, and more. The properties and possible commands for all object types are given in the object dictionary. Objects are accessed in scripts through object names that must:
- Begin in a letter
- Contain any number of letters, numbers, and the underscore characters
Although script variables traditionally start in number sign (#), they are not required to do so. Some object commands, however, require a number sign to distinguish variables from object names. It is therefore recommend that internal scripts always start variables with a number sign such that names without a number sign are always object names.
Whenever an object name is needed for an existing object, such as when targeting a command or as arguments for commands, the object name can be dereferenced through a variable by using ^#name
. The caret, ^
, means to use the object whose name is equal to the value of the provided variable (here #name
).
When writing internal scripts, object names are global. Subroutines should be careful not to overwrite objects in the main commands. When writing a subroutine whose result is to define an object, the main commands can access any objects using the name defined in the subroutine. Because subroutine arguments are only strings that are assigned to variables, passing an object to a subroutine must use one of the following two methods:
Sub UseObject,#obj GetObject obj,#obj obj.0.get "#listItem" ! ... or directly dereference the object name ^#obj.1.get passedObj EndSub CreateList mylist,"one string item",anObject GoSub UseObject,"mylist"
The object name mylist
is passed as a string that gets set to the subroutine variable #obj
. The GetObject command evaluates that variable as an object name and then sets obj
to that object. Alternatively, the object can be directly dereferenced with ^#obj
.
A common task for internal scripts is to automate running calculations. When a script tells a commands document to interpret its commands or to interpret and run calculations, all variables defined in the script are transferred to the document. The typical script will define variables to control a calculation and then run one or more calculations.
Most FEA or MPM commands documents are written as stand-alone documents, which means they define all their own variables. To allow such documents to use script-defined variables when run from an internal script but their own variables when run on their own, a running script will also define a read only variable named _ScriptMode_
. Thus, an FEA or MPM commands document can contain a section like:
ifNDef _ScriptMode_ #myVar = 23 (define variables to run as stand-alone file) ...
endif
When this FEA or MPM commands document is run in script control, the script will be expected to define all the variables defined in the above block and the commands document will use the script-defined variables instead of it's local variables. When that document is run by itself, however, it will execute the above section and define all variables needed to run as a stand-alone file.
A Sample Internal Script
The following sample internal script, opens the front Command document, runs one calculation, and reads and writes out the maximum stress in the y direction:
! First command must be "Script" Script ! Find the front commands document nfmapp.get cdoc,"frontCommandDocument" ! Set variables needed by calculations #strain=2 ! Interpret and run calculaitons cdoc.run rdoc,"output.mpm" ! Get stress from a time plot CreateDictionary settings settings.setStringForKey "Stress","menutext" settings.setStringForKey "1","tensorindex" settings.setStringForKey "1","materialoption" rdoc.timePlot data,settings ! data is a list with two lists, grab y data ! and seach for maximum value data.1.get ydata #smax=-1e6 Repeat "#k",1,@ydata.count-1 #sval=@ydata.#k if #sval>#smax #smax = #sval endif EndRepeat ! Write results to script console pabe WriteLine "Maximum syy = "smax
The "Script" command marks these command as an internal scripts. All internal scripts have nfmapp
defined as object name for the NairnFEAMPM application. That object is used to fetch the front Command document. Next variables needed by the script are set and the run command runs the calculation. The rest of this script plots average stress in the y direction (by entering plot settings into a created dictionary) and then loops over y values from the returned results (in lists) to find the maximum value. Finally, the maximum value is printed to the script's console pane.
Internal Scripting Commands
Besides the standard commands in the interpretive language, internal scripting adds some direct commands specific to internal scripting and many object commands that can be targeted to objects . The first "direct" command is:
Script
This command must be the first command in a script. Its presence is how NairnFEAMPM knows to interpret the commands as an internal script rather than as commands to setup FEA or MPM calculations.
All remaining "direct" commands are listed below while object commands are in the following section. Each command is documented with command name and arguments. Required arguments are listed with the command; optional arguments are enclosed in square brackets:
command (arg1),(arg2),[(arg3)],... obj[.#i].command (arg1),(arg2),[(arg3)],...
The first is a "direct" command. The second is a command sent to a specific object. The optional .#i
is an object extractor that can pick a object from a list by index starting at 0. The index can be a variable containing a number. All command arguments (e.g., (arg1)
, (arg2)
, ...) are evaluated first as an expression and the expression result is passed to the command. Two consequences of this process are:
- Many commands return a result in a variable that must be provided as a command argument. Such arguments are listed below as
"#var"
. This quoted form is actually a string expression that evaluates to#var
that is passed to the command. If needed, you could use an expression that evaluates to the name as well, such as:#ref = "#var" command #ref
Finally, note that although the internal scripting language does not require variables to start with a # sign, variables names passed to scripting commands to retrieve results are required to being in a # sign (a good approach is just to use # sign for all variables in internal scripts). - Other internal scripting commands return an object as their result. These commands expect the object name (denoted below by
objName
) to be passed as a string expression that evaluates to the object's name. Because object names cannot start in#
, they typically act as expressions that just evaluate to their name even when not quoted. If there is ever a name conflict, put the object name in quotes. (Note: the requirement that"#var"
passed to a command must start with a # sign is to guarantee that commands can distinguish between variables and objects). - When an internal scripting command argument expects an object name parameter to refer to an existing object, it is listed as
objName[.#i]
. The optional.#i
is an object locator that can pick an existing object from a list by index.
Direct Commands
This section has all the extra direct commands for internal scripts (in alphabetical order):
CreateDictionary (objName)
Creates a new dictionary object and sets(objName)
to that dictionary. See dictionary object definition for properties and available object commands.
CreateList (objName),[(arg1)],[(arg2)],...
Creates a new list object and sets(objName)
to that list. The command can include any number of optional expressions and/or object names and they are all added to the new list. The object names must be direct names and not extracted from a list usingobjName.#i
. See list object definition for properties and available object commands.Export [(path)]
This command will save the contents of the script window's console pane to the file specified by(path)
. The optional(path)
can be a full path or a path relative to the script document. The folder to receive the output file must already exist. If(path)
is omitted, the user is given a file-saving dialog box to select file name and save location.GetObject objName1,objName2[.#i]
Because object names cannot be used in expressions, this command provides the equivalent ofobjName1 = objName2[.#i]
when needed. IfobjName2[.#i]
is not a valid object,objName1
will be set to None object that can be checked with ifDef or ifNDef conditionals. One common use is to pass objects to subroutines.Open (doc),[(path)]
Open a document and set the object variable in(doc)
(which must be a valid object name or an expression that evaluates to an valid object name) to the opened document. The optional(path)
argument can have the following values:- A full or relative path to an existing file: The file will be opened. Full paths start with "/". Relative paths are relative the the location of the saved script file.
_commands_
: will open (and bring to the front) the first commands window that is found (not counting the commands window with the running script)._results_
: will open (and bring to the front) the first results window that is found.- Omitted: if the
(path)
argument is omitted, the user is presented a standard file-opening dialog box and asked to select the file to be opened.
OpenFolder (strVar),[(title)],[(path)]
This command will select a folder and create it if needed. If the optional(path)
variable is omitted, this command presents the user with a file opening dialog that can select only folders (and can create new folders if desired). If provided, the title of the folder selection window will be(title)
. If optional(path)
is provided, that folder will be created (along with all intervening folders). The(path)
can be a full path or relative to the script file (note: when providing(path)
, you must also provide(title)
, but it can be anything because it is ignored).
When done, the(strVar)
(which must contain an unquoted and valid variable name and cannot be an expression) will be set to the full path to the selected or created folder. If a selection process is cancelled, the variable will be set to an empty string.UserInput "#var",(title),(prompt),<(initialText)>,<(btn1)>,<(btn2)>,<(btn3)>
Will display a dialog box where the user can enter one line of text. Thetitle
is displayed in the title bar of the window. The(prompt)
is displayed above the text field to explain the requested input (it can be any length and use multiple lines). The three optional buttons can change the text of the default "OK" and "Cancel" buttons and optionally add a third button. The results are returned in a variable array using the provided name ---#var[1]
set to text of clicked button and#var[2]
set to text entered by the user (also sets#var[0]=2
).
Scripting Commands for Objects
This section has all object commands (in alphabetical order). Note that a command to an invalid object (i.e., obj[.#i].(command)
where obj[.#i]
is not an existing object) or passing an invalid object to a command that expects an object (i.e., when obj[.#i]
is in the list of command arguments) will, unless otherwise noted, cause an error and the script will end. Two important exceptions are the GetObject and get commands. When needed, you can use these commands to validate any object before targeting it with other commands or using it an "@" expression to read an object property.
- obj[.#i].addList objName1[.#i],[objName2[.#i],...]
- Adds individual elements of one or more lists to the target object. Any parameters that do not correspond to a valid list object will be skipped. Use addObject to add a list as a single object to another list.
Supported By: lists - obj[.#i].addObject objName1[.#i],[objName2[.#i],...]
- Adds one or more objects to the target list. Any parameters that do not correspond to a valid object will be skipped. Objects that are other lists are added as list objects (i.e., a list can contain other lists). Use addList to add elements of those lists to the target list.
Supported By: lists - obj[.#i].addString (expr1),[(expr2),...]
- Adds one or more strings to the target list. All parameters must valid expressions.
Supported By: lists - obj[.#i].close
- Closes the document and all its windows. If the document has been changed, any changes are lost.
Supported By: Command documents, Results documents - obj[.#i].CrackClosure "objVar",(tipnode),<(normT)>,<(shearT)>
- Calculate mode I and mode II energy release rates for the crack tip at the specified (tipnode). It will set object with name "objVar" to a dictionary with entries for "GI", "GII", and "Gtot" for the energy release rates. The returned dictionary will have other calculation details as well (similar to what appears in the crack closure window). If there is a error, the returned record will have single entry "ERROR" that describes the error. The tractions allow specification of constant crack-surface tractions to use in the calculations (they are zero if omitted)
Supported By: Results documents obj[.#i].export <(path)>
- This command will save the contents of the console pane in the object document to the file specified by
(path)
. The optional(path)
can be a full path or a path relative to the script document. The folder to receive the output file must already exist. If(path)
is omitted, the user is given a file-saving dialog box to select file name and save location.
Supported by: Command documents - obj[.#i].FindNode "#var",(x),(y)
- Finds the node in a 2D grid closest to the coordinates in the provided (x) and (y) parameters. The provided variable, quoted
#var
, is set equal to the node number or set to 0 if none found.
Supported By: Results documents - obj[.#i].get ("#var" or objName),[(attr)]
- The response of this command depends on the target object in
obj[.#i]
:
1. Ifobj[.#i]
is a string or number, set#var
to that value. The first parameter must be a valid variable name (starting in "#") and(attr)
is ignored. Note that whenobj
is a List containing strings or numbers, this special case can also be done with an "@" expression instead:#var=@obj.#i
2. Ifobj[.#i]
is not a string, setobjName
(which must be a valid object name in the first parameter) to one of that object's "to-many" or "to-single" attributes defined by(attr)
. But, if optional(attr)
is not provided, setobjName
to the object extracted byobj[.#i]
3. Ifobj[.#i]
does not correspond to a valid object, this command will not cause an error. Instead, if the first parameter is "#var", that variable will be removed from the list of variables. If the first parameter isobjName
, the object name will set to None. Both these can be used to validateobj[.#i]
with ifDef or ifNDef commands before using it in subsequent scripting that might cause an error.
Supported By: all objects that that have attributes or properties and to get elements from lists - obj[.#i].insertObject objName[.#i],(index)
- Inserts one object at
index
in the target list. The providedobjName[.#i]
must be a valid object name and list indices are zero based.
Supported By: lists - obj[.#i].insertString (expr),(index)
- Inserts one string at
index
in the target list. The provided(expr)
must be a valid expression and list indices are zero based.
Supported By: lists obj[.#i].interpret
- Interpret the commands in the object document. The resulting XML commands will appear in the console pane of that document. This command will wait until the interpretations are done before returning control to the script. One use of this command is to follow it with an
object.export
command to save the XML commands to a file.
Supported by: Command documents - obj[.#i].join "#var",[(string)]
- Joins all elements in the target object (which must be a list) separated by the optional
(string)
(if omitted joined by empty string). To work correctly, all elements in the target list must be strings. The provided variable, quoted#var
, is set equal to the joined strings.
Supported By: lists obj[.#i].plottable (table)
- This command will plot a table of data as a child window of the object document where
(table)
is a string argument of multiple lines. The first column has x data and all subsequent, tab-delimited columns have one or more y data sets. A column with no data for specific x can be left empty. The(table)
can include a preamble of commands to set styles for the plot. These lines are at the beginning of the table, each begin with "#", and can use any commands documented in the PublishPlot application. A singleplottable
command can plot multiple tables if they are separated by blank lines within the(table)
string argument. The use of multipleplottable
commands will create multiple plot windows.
Supported by: Results documents - obj[.#i].pop ("#var" or objName)
- The command will get the last element of the target object in
obj[.#i]
, which must be a List, and will remove that element from the list. If the element is a string, the variable#var
will be set to that element. If it as object, theobjName
will be set to that element. If the list is empty, this command will not cause an error. Instead, if the first parameter is"#var"
, that variable will be removed from the list of variables. If the first parameter isobjName
, that object name will set to None.
Supported By: Lists - obj[.#i].remove (index)
- Remove item in a list at
(index)
(which can be any valid integer expression).
Supported By: lists - obj[.#i].removeValueForKey (key)
- Remove value in a dictionary corresponding to
(key)
(which can be any valid expression).
Supported By: dictionaries obj[.#i].run (resDoc),(path)
- Interpret the commands in the object document, run the calculations (locally), save the result to the results document using the
(path)
argument, and finally set the object variable in(resDoc)
(which must be a valid object name and not an expression) to the final results document. This command will wait until the calculations are done before returning control to the script. The(path)
can be a full path or a path relative to the script document. The folder to receive the output file must already exist.
Supported by: Command documents obj[.#i].runremote
- Java app only
- obj[.#i].setObjectForKey objName1[.#i],(key)
obj[.#i].setStringForKey (expr),(key)
obj[.#i].setNumberForKey (expr),(key) - These three commands set a single key-value pair in a dictionary object (
obj[.#i]
must be a dictionary). Three commands are available to add three types of values using a(key)
, which can be any string or numeric expression. The first one adds any valid object to the dictionary. The other two add any valid expression (in(expr)
) to the dictionary. The main use forsetNumberForKey
is in scripts that will later use the keysSortedByNumericValues relation of the dictionary.
Supported By: dictionaries - obj[.#i].sort
- Sorts the items in list by case insensitive comparisons. All items must be strings.
Supported By: lists - obj[.#i].subList objName,start,[end]
- The target object (in
obj[.#i]
) must be a list. This command creates a new list, which is stored inobjName
, containing elements from indexstart
to indexend-1
(note the first element in a list is at index 0). If optionalend-1
is omitted, the sublist will be fromstart
to the end of the list.
Supported By: lists obj[.#].timePlot objName,settings
- Plots a selected MPM result as a function of time and returns the result in
objName
as a list with two lists at index 0 and 1 for time and values, respectively. The result to be plotted and options for the plot window are determined by the plot settings loaded intosettings
which must be a dictionary. See the xy plot command to get a 2D plot of a result through an FEA mesh or an MPM grid.
Supported by: Results Documents - obj[.#i].valueForKey ("#var" or objName),(key)
- Fetches the value from a dictionary (
obj[.#i]
must be a dictionary object) corresponding to(key)
, which is any valid expression. If the value is a string or a number, set#var
(which must be a quoted variable name starting in "#") to that value. If the value is an object, setobjName
(which must be a valid object name) to that object. A mismatch between value type and the first parameter (e.g., usingobjName
when value is a string or number or using"#var"
when value is an object) will cause an error. If(key)
is not in the dictionary,"#var"
will be undefined orobjName
will set to None type. Both these can be checked as explained in the get command.
Supported By: dictionaries obj[.#i].XYPlot objName,settings
- Plots a selected MPM or FEA result as a function of position in a mesh or grid and returns the result in
objName
as a list with two list at index 0 and 1 for distance and values, respectively. The result to be plotted and options for the plot window are determined by the plot settings. See the time plot command to plot an MPM result as a function of time.
Supported by: Results Documents