As of version 0.7.1, the way to define properties for elements of the geometry has changed thoroughly. As a result, the property system has become much more flexibel and powerful, and can be used for Formex data structures as well as for TriSurfaces and Finite Element models.
With properties we mean any data connected with some part of the geometry other than the coordinates of its points or the structure of points into elements. Also, values that can be calculated purely from the coordinates of the points and the structure of the elements are usually not considerer properties.
Properties can e.g. define material characteristics, external loading and boundary conditions to be used in numerical simulations of the mechanics of a structure. The properties module includes some specific functions to facilitate assigning such properties. But the system is general enough to used it for any properties that you can think of.
Properties are collected in a PropertyDB object. Before you can store anything in this database, you need to create it. Usually, you will start with an empty database.
P = PropertyDB()
Now you can start entering property records into the database. A property record is a lot like a Python dict object, and thus it can contain nearly anything. It is implemented however as a CascadingDict object, which means that the key values are strings and can also be used as attributes to address the value. Thus, if P is a property record, then a field named key can either be addressed as P[‘key’] or as P.key. This implementation was choosen for the convenience of the user, but has no further advantages over a normal dict object. You should not use any of the methods of Python’s dict class as key in a property record: it would override this method for the object.
The property record has four more reserved (forbidden) keys: kind, tag, set, setname and nr. The kind and nr should never be set nor changed by the user. kind is used internally to distinguish among different kind of property records (see Node properties). It should only be used to extend the PropertyDB class with new kinds of properties, e.g. in subclasses. nr will be set automatically to a unique record number. Some application modules use this number for identification and to create automatic names for property sets.
The tag, set and setname keys are optional fields and can be set by the user. They should however only be used for the intended purposes explained hereafter, because they have a special meaning for the database methods and application modules.
The tag field can be used to attach an identification string to the property record. This string can be as complex as the user wants and its interpretation is completely left to the user. The PropertyDB class just provides an easy way to select the records by their tag name or by a set of tag names. The set and setname fields are treated further in Using the set and setname fields.
So let’s create a property record in our database. The Prop() method does just that. It also returns the property record, so you can directly use it further in your code.
>>> Stick = P.Prop(color='green',name='Stick',weight=25,\
comment='This could be anything: a gum, a frog, a usb-stick,...'})
>>> print Stick
color = green
comment = This could be anything: a gum, a frog, a usb-stick,...
nr = 0
name = Stick
weight = 25
Notice the auto-generated nr field. Here’s another example, with a tag:
>>> author = P.Prop(tag='author',name='Alfred E Neuman',\
address=CascadingDict({'street':'Krijgslaan',\
'city':'Gent','country':'Belgium'}))
>>> print author
nr = 1
tag = author
name = Alfred E Neuman
address =
city = Gent
street = Krijgslaan
country = Belgium
This example shows that record values can be complex structured objects. Notice how the CascadingDict object is by default printed in a very readible layout, offsetting each lower level dictionary two more postions to the right.
The CascadingDict has yet another fine characteristic: if an attribute is not found in the toplevel, all values that are instances of CascadingDict or Dict (but not the normal Python dict) will be searched for the attribute. If needed, this searching is even repeated in the values of the next levels, and further on, thus cascading though all levels of CascadingDict structures until the attribute can eventually be found. The cascading does not proceed through values in a Dict. An attribute that is not found in any of the lower level dictionaries, will return a None value.
If you set an attribute of a CascadingDict, it is always set in the toplevel. If you want to change lower level attributes, you need to use the full path to it.
>>> print author.st
Krijgslaan
>>> author.street = 'Voskenslaan'
>>> print author.street
Voskenslaan
>>> print author.address.street
Krijgslaan
>>> author.address.street = 'Wiemersdreef'
>>> print author.address.street
Wiemersdreef
>>> author = P.Prop(tag='author',alias='John Doe',\
address={'city': 'London', 'street': 'Downing Street 10',\
'country': 'United Kingdom'})
>>> print author
nr = 2
tag = author
alias = John Doe
address = {'city': 'London', 'street': 'Downing Street 10',\
'country': 'United Kingdom'}
In the examples above, we have given a name to the created property records, so that we could address them in the subsequent print and field assigment statements. In most cases however, it will be impractical and unnecessary to give your records a name. They all are recorded in the PropertyDB database, and will exist as long as the database variable lives. There should be a way though to request selected data from that database. The getProp() method returns a list of records satisfying some conditions. The examples below show how it can be used.
>>> for p in P.getProp(rec=[0,2]):
print p.name
Stick
John Doe
>>> for p in P.getProp(tag=['author']):
print p.name
None
John Doe
>>> for p in P.getProp(attr=['name']):
print p.nr
0
2
>>> for p in P.getProp(tag=['author'],attr=['name']):
print p.name
John Doe
The first call selects records by number: either a single record number or a list of numbers can be specified. The second method selects records based on the value of their tag field. Again a single tag value or a list of values can be specified. Only those records having a ‘tag’ filed matching any of the values in the list will be returned. The third selection method is based on the existence of some attribute names in the record. Here, always a list of attribute names is required. Records are returned that posess all the attributes in the list, independent from the value of those attributes. If needed, the user can add a further filtering based on the attribute values. Finally, as is shown in the last example, all methods of record selection can be combined. Each extra condition will narrow the selection further down.
In the examples above, the property records contained general data, not related to any geometrical object. When working with large geometrical objects (whether Formex or other type), one often needs to specify properties that only hold for some of the elements of the object.
The set can be used to specify a list of integer numbers identifying a collection of elements of the geometrical object for which the current property is valid. Absence of the set usually means that the property is assigned to all elements; however, the property module itself does not enforce this behavior: it is up to the application to implement it.
Any record that has a set field, will also have a setname field, whose value is a string. If the user did not specify one, a set name will be auto-generated by the system. The setname field can be used in other records to refer to the same set of elements without having to specify them again. The following examples will make this clear.
>>> P.Prop(set=[0,1,3],setname='green_elements',color='green')
P.Prop(setname='green_elements',transparent=True)
>>> a = P.Prop(set=[0,2,4,6],thickness=3.2)
P.Prop(setname=a.setname,material='steel')
>>> for p in P.getProp(attr=['setname']):
print p
color = green
nr = 3
set = [0 1 3]
setname = green_elements
nr = 4
transparent = True
setname = green_elements
nr = 5
set = [0 2 4 6]
setname = Set_5
thickness = 3.2
nr = 6
material = steel
setname = Set_5
In the first case, the user specifies a setname himself. In the second case, the auto-generated name is used. As a convenience, the user is allowed to write set=name instead of setname=name when referring to an already defined set.
>>> P.Prop(set='green_elements',transparent=False)
for p in P.getProp(attr=['setname']):
if p.setname == 'green_elements':
print p.nr,p.transparent
3 None
4 True
7 False
Record 3 does not have the transparent attribute, so a value None is printed.
The property system presented above allows for recording any kind of values. In many situations however we will want to work with a specialised and limited set of attributes. The main developers of e.g. often use the program to create geometrical models of structures of which they want to analyse the mechanical behavior. These numerical simulations (FEA, CFD) require specific data that support the introduction of specialised property records. Currently there are two such property record types: node properties (see Node properties), which are attributed to a single point in space, and element properties (Element properties), which are attributed to a structured collection of points.
Special purpose properties are distincted by their kind field. General property records have kind=”, node properties haven kind=’n’ and kind=’e’ is set for element properties. Users can create their own specialised property records by using other value for the kind parameter.
Node properties are created with the nodeProp() method, rather than the general Prop(). The kind field does not need to be set: it will be done automatically. When selecting records using the getProp() method, add a kind=’n’ argument to select only node properties.
Node properties will recognize some special field names and check the values for consistency. Application plugins such as the Abaqus input file generator depend on these property structure, so the user should not mess with them. Currently, the following attributes are in use:
as a list of 6 items [ u_0, u_1, u_2, r_0, r_1, r_2 ]. These items have 2 possible values:
- 0
The degree of freedom is not restrained.
- 1
The degree of freedom is restrained.
as a string. This string is a standard boundary type. Abaqus will recognize the following strings:
PINNED
ENCASTRE
XSYMM
YSYMM
ZSYMM
XASYMM
YASYMM
ZASYMM
Some simple examples:
P.nodeProp(cload=[5,0,-75,0,0,0])
P.nodeProp(set=[2,3],bound='pinned')
P.nodeProp(5,displ=[(1,0.7)])
The first line sets a concentrated load all the nodes, the second line sets a boundary condition ‘pinned’ on nodes 2 and 3. The third line sets a prescribed displacement on node 5 with value 0.7 along the first direction. The first positional argument indeed corresponds to the ‘set’ attribute.
Often the properties are computed and stored in variables rather than entered directly.
P1 = [ 1.0,1.0,1.0, 0.0,0.0,0.0 ]
P2 = [ 0.0 ] * 3 + [ 1.0 ] * 3
B1 = [ 1 ] + [ 0 ] * 5
CYL = CoordSystem('cylindrical',[0,0,0,0,0,1])
P.nodeProp(bound=B1,csys=CYL)
The first two lines define two concentrated loads: P1 consists of three point loads in each of the coordinate directions; P2 contains three force moments around the axes. The third line specifies a boundary condition where the first DOF (usually displacement in -direction) is constrained, while the remaining 5 DOF’s are free. The next line defines a local coordinate system, in this case a cylindrical coordinate system with axis pointing from point [0.,0.,0.] to point [0.,0.,1.]. The last line
To facilitate property selection, a tag can be added.
nset1 = P.nodeProp(tag='loadcase 1',set=[2,3,4],cload=P1).nr
P.nodeProp(tag='loadcase 2',set=Nset(nset1),cload=P2)
The last two lines show how you can avoid duplication of sets in mulitple records. The same set of nodes should receive different concentrated load values for different load cases. The load case is stored in a tag, but duplicating the set definition could become wasteful if the sets are large. Instead of specifying the node numbers of the set directly, we can pass a string setting a set name. Of course, the application will need to know how to interprete the set names. Therefore the property module provides a unified way to attach a unique set name to each set defined in a property record. The name of a node property record set can be obtained with the function Nset(nr), where nr is the record number. In the example above, that value is first recorded in nset1 and then used in the last line to guarantee the use of the same set as in the property above.
The elemProp() method creates element properties, which will have their kind attribute set to ‘e’. When selecting records using the getProp() method, add the kind=’e’ argument to get element properties.
Like node properties, element property records have a number of specialize fields. Currently, the following ones are recognized by the Abaqus input file generator.
The data collected in property records can be very diverse. At times it can become quite difficult to keep these data consistent and compatible with other modules for further processing. The property module contains some data classes to help you in constructing appropriate data records for Finite Element models. The FeAbq module can currently interprete the following data types.
CoordSystem defines a local coordinate system for a node. Its constructor takes two arguments:
Thus, CoordSystem('C',[0.,0.,0.,0.,0.,1.]) defines a cylindrical coordinate system with the global as axis.
ElemLoad is a distributed load on an element. Its constructor takes two arguments:
E.g., ElemLoad(‘PZ’,2.5) defines a distributed load of value 2.5 in the direction of the -axis.
ElemSection can be used to set the material and section properties on the elements. It can hold:
An example:
>>> steel = {
'name': 'steel',
'young_modulus': 207000,
'poisson_ratio': 0.3,
'density': 0.1,
}
>>> thin_plate = {
'name': 'thin_plate',
'sectiontype': 'solid',
'thickness': 0.01,
'material': 'steel',
}
>>> P.elemProp(eltype='CPS3',section=ElemSection(section=thin_plate,material=steel))
First, a material is defined. Then a thin plate section is created, referring to that material. The last line creates a property record that will attribute this element section and an element type ‘CPS3’ to all elements.