You can extend the functionality of the ABAQUS Scripting Interface by writing your own modules that contain classes and functions to accomplish tasks that are not directly available in ABAQUS. For example, you can write a function to print the names of all materials that have a density specified, or you can write a function that creates a contour plot using a custom set of contour plot options. Creating functions and modules in Python is described in Creating functions, Section 4.6.1, and Functions and modules, Section 4.6.5.
This section describes how you can extend the functionality of the ABAQUS Scripting Interface. The following topics are covered:
If you extend the kernel functionality by writing your own classes and functions, you may want to store data required by those classes or functions in the ABAQUS/CAE model database so the data are available the next time you open the database. To store custom kernel data in the ABAQUS/CAE model database, you must make use of the customKernel module. The customKernel module augments the mdb object with a member called customData. When you save a model database, ABAQUS/CAE also saves any data created below the customData object.
For example,
import customKernel mdb = Mdb() mdb.customData.myString = 'The width is ' mdb.customData.myNumber = 58 mdb.saveAs('custom-test.cae') mdb.close()If you start a new session and open the model database, custom-test.cae, you can refer to the variables that you saved. For example,
>>> mdb = openMdb('custom-test.cae') >>> print mdb.customData.myString, mdb.customData.myNumber The width is 58
You can store almost any type of Python object under mdb.customData; for example, strings, numbers, and Python classes. However, there are some restrictions; for example, you cannot store file objects. These restrictions are due to the fact that the ABAQUS/CAE infrastructure uses Python’s pickle module to store the customData object in the model database. The pickle module allows the Python programmer to write a data structure to a file and then recreate that data structure when reading from the file. For details on the restrictions imposed by the pickle module, see the official Python web site (www.python.org).
ABAQUS/CAE does not keep track of changes made to the customData object. As a result, when the user quits a session, ABAQUS/CAE will not prompt them to save their changes if they changed only objects under customData.
In addition to providing a persistence mechanism, the customKernel module contains classes that provide the following capabilities:
Querying custom kernel data values from the GUI. From a GUI script you can access some attribute of your custom kernel object, just as you would from the kernel. For example,
print mdb.customData.myObject.name
Notification to the GUI when custom kernel data change. For example, you can have a manager dialog box that lists the objects in a repository. When the contents of the repository change, you can be notified and take the appropriate action to update the list of objects in the manager dialog box.
To make use of these features, you must derive your custom kernel objects from the classes listed in the following sections. For more details on GUI customization, see the ABAQUS GUI Toolkit Reference Manual.
You can use the CommandRegister class to derive a general class that can be queried from the GUI. In addition, the class can notify the GUI when its contents change. For example,
class Block(CommandRegister): def __init__(self, name, ...): CommandRegister.__init__(self) ...
If a query is registered by the GUI on an instance of this class, the GUI will be notified when a member of this instance is changed, added, or deleted, For more details on registering queries, see the ABAQUS GUI Toolkit Reference Manual.
The first argument to the constructor of a class derived from CommandRegister must be a string representing the name of the object. That string will automatically be assigned by the infrastructure to a member called name.
Repositories are containers that hold objects that are keyed by strings. It may be convenient to store your custom kernel objects in repositories, in the same way that ABAQUS/CAE part objects are stored in the Parts repository.
The customData object is an instance of a RepositorySupport class, which provides a Repository method that allows you to create a repository as an attribute of the instance. For more information, see RepositorySupport, Section 5.6.6. The arguments to the Repository method are the name of the repository and a constructor or a sequence of constructors. Instances of these constructors will be stored in the repository. For more information, see Repository object, Section 47.3 of the ABAQUS Scripting Reference Manual.
Since repositories are designed to notify the GUI when their contents change, the objects placed inside them should be derived from either CommandRegister or RepositorySupport to extend this capability to its fullest.
The ABAQUS Scripting Interface uses the following conventions:
The name of a repository is a plural noun with all lowercase letters.
A constructor is a capitalized noun (or a combination of capitalized nouns and adjectives).
The first argument to the constructor must be name.
from customKernel import CommandRegister class Block(CommandRegister): def __init__(self, name): CommandRegister.__init__(self) self.name = name mdb.customData.Repository('blocks', Block) mdb.customData.Block(name='Block-1') block = mdb.customData.blocks['Block-1']
Repositories have several useful methods for querying their contents, as shown in the following table:
Method | Description |
keys() | Returns a list of the keys in the repository. |
has_key() | Returns 1 if the key is found in the repository; otherwise, returns 0. |
values() | Returns a list of the objects in the repository. |
items() | Returns a list of key, value pairs in the repository. |
changeKey(fromName, toName) | Changes the name of a key in the repository. This method will also change the name attribute of the instance in the repository. |
from customKernel import CommandRegister class Block(CommandRegister): def __init__(self, name): CommandRegister.__init__(self) self.name = name mdb.customData.Repository('blocks', Block) mdb.customData.Block(name='Block-1') mdb.customData.Block(name='Block-2') print 'The original repository keys are: ', mdb.customData.blocks.keys() print mdb.customData.blocks.has_key('Block-2') print mdb.customData.blocks.has_key('Block-3') mdb.customData.blocks.changeKey('Block-1', 'Block-11') print 'The modified repository keys are: ', mdb.customData.blocks.keys() print 'The name member is ', mdb.customData.blocks['Block-11'].name print 'The repository size is', len(mdb.customData.blocks)The resulting output is
The original repository keys are ['Block-1', 'Block-2'] 1 0 The modified repository keys are ['Block-11', 'Block-2'] The name member is Block-11 The repository size is 2
You can use the RepositorySupport class to derive a class that can contain one or more repositories. However, if you do not intend to create a repository as an attribute of your class, you should derive your class from CommandRegister, not from RepositorySupport.
Using the RepositorySupport class allows you to create a hierarchy of repositories; for example, in the ABAQUS Scripting Interface the parts repository is a child of the models repository. Objects stored in repositories must have a member called name. This member is automatically created by the infrastructure using the first argument passed into your constructor. To create a hierarchy of repositories, derive your class from RepositorySupport and use its Repository method to create child repositories as shown below. The Repository method is described in Repositories, Section 5.6.4.
from abaqus import * from customKernel import CommandRegister, RepositorySupport class Block(CommandRegister): def __init__(self, name): CommandRegister.__init__(self) self.name = name class Model(RepositorySupport): def __init__(self, name): RepositorySupport.__init__(self) self.Repository('blocks', Block) mdb.customData.Repository('models', Model) mdb.customData.Model('Model-1') mdb.customData.models['Model-1'].Block('Block-1') model_1 = mdb.customData.models['Model-1'] block_1 = mdb.customData.models['Model-1'].blocks['Block-1']
You use the RegisteredDictionary class to create a dictionary that can be queried from the GUI. In addition, the infrastructure can notify the GUI when the contents of the dictionary change. The key of a registered dictionary must be either a String or an Int. The values associated with a key must all be of the same type; for example, all integers or all strings. The RegisteredDictionary class has the same methods as a Python dictionary. In addition, the RegisteredDictionary class has a changeKey method that you use to rename a key in the dictionary. For example,
from customKernel import RegisteredDictionary mdb.customData.myDictionary = RegisteredDictionary() mdb.customData.myDictionary['Key-1'] = 1 mdb.customData.myDictionary.changeKey('Key-1', 'Key-2')
You use the RegisteredList class to create a list that can be queried from the GUI. In addition, the infrastructure can notify the GUI when the contents of the list change. The values in the list must all be of the same type; for example, all integers or all strings. The RegisteredList has the same methods as a Python list. For example, appending Item-1 to the list in the following statements causes the infrastructure to notify the GUI that the contents of the list have changed:
from customKernel import RegisteredList mdb.customData.myList = RegisteredList() mdb.customData.myList.append('Item-1')
You use the RegisteredTuple class to create a tuple that can be queried from the GUI. In addition, the infrastructure can notify the GUI when the contents of any of the members of the tuple change. The members in the tuple must derive from the CommandRegister class, and the values in the tuple must all be of the same type; for example, all integers or all strings. For example,
from abaqus import * from customKernel import CommandRegister, RegisteredTuple class Block(CommandRegister): def __init__(self, name): CommandRegister.__init__(self) self.name = name mdb.customData.Repository('blocks', Block) block1 = mdb.customData.Block(name='Block-1') block2 = mdb.customData.Block(name='Block-2') tuple = (block1, block2) mdb.customData.myTuple = RegisteredTuple(tuple)
The customKernel module also provides a session.customData object that allows you to store data on the session object and query it from the GUI. Data stored on the session object persist only for the current ABAQUS/CAE session. When you close the ABAQUS/CAE session, ABAQUS does not store any of the data below session.customData on the model database. As a result, these data will be lost, and you will not be able to retrieve these data when you start a new session and open the model database. The session object is useful for maintaining data relevant to the current session only, such as the current model or output database.
The same methods and classes that are available for mdb.customData are available for session.customData.
If you have custom kernel scripts that store data in a model database, you should verify that the model database is compatible with your scripts before allowing the user to interact with the model database. For example, if you have two different custom kernel applications that are not designed to work independently on the same model database, you should prevent a model database that was created with the first application from being operated on by the second application.
You can add the attributes that are necessary to track information about your custom application by deriving your own appData object. You use the setAppData method to install this object as session.customData.appData. You can call the setAppData only once, which prevents unauthorized changes to the object. For example, the following script illustrates how you can store the application name and version numbers on the appData object:
import customKernel class MyAppData(customKernel.AbaqusAppData): name = 'My Application' majorVersion = 1 minorVersion = 1 updateVersion = 1 customKernel.setAppData(MyAppData())
If you save a model database that does not have any appData associated with it, ABAQUS/CAE copies the session.customData.appData object to mdb.customData.appData. When you subsequently import the customKernel module and open the model database, ABAQUS/CAE calls the session.customData.verifyMdb method and passes in the mdb.customData.appData object.
You must write the verifyMdb method and install it using the setVerifyMdb method. You can call the setVerifyMdb method only once, which prevents unauthorized changes to the object. In the following example, if the verifyMdb method throws an exception, ABAQUS/CAE issues an error message and opens a new model database. In addition, ABAQUS/CAE does not load the rest of the mdb.customData object. Opening a new model database forces ABAQUS/CAE to close the model database that triggered the exception and prevents the user from interacting with it. If no exception is thrown, the major version number is checked. If the user needs to upgrade the model database, the script invokes the loadCustomData method. The loadCustomData method forces the loading of the mdb.customData object so that changes can be made to it.
def verifyMdb(mdbAppData): # session.customData.appData was initialized using setAppData # appName = session.customData.appData.name majorVersion = session.customData.appData.majorVersion # Verify the MDB that the user is attempting to open by # comparing its attributes to the application's attributes. # try: mdbAppName = mdbAppData.name mdbMajorVersion = mdbAppData.majorVersion except: Mdb() raise ValueError, \ 'Error trying to access MDB customData attributes.' if mdbAppName != appName: raise ValueError, \ 'This MDB is not supported by this application.' # Perform a customData upgrade if needed. # if mdbMajorVersion < majorVersion: upgradeMajorVersion() #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def upgradeMajorVersion(): # mdb.customData is not loaded until verifyMdb returns # without raising an exception. Force the loading # of mdb.customData so that we can upgrade some of its # attributes. # customKernel.loadCustomData() <perform upgrades here> # Set the verifyMdb method for the application. # customKernel.setVerifyMdb(verifyMdb)