Solver Attributes and Data Names

Solver specific data created from the HyperMesh template system is stored in card images. Each piece of data that defines a card image has a text string (data name) and a numeric attribute ID.

An example is the Young’s Modulus for a material. Each solver, and even each different material type for a particular solver, can have a Young’s Modulus attribute and a corresponding data name. These data names and attributes are defined in each solver’s feoutput template. They are unique and are not necessarily consistent between solvers or even between each material within a solver.

Templates exist for each solver supported by HyperMesh and are located in subfolders under the <altair_home>/templates/feoutput directory. These templates define every solver specific attribute including data names, attribute IDs, card image formats, and the format of the data upon export. The *defineattribute command is used to define attribute data names and IDs in a template file.

Solver data names are not documented, as they may change often as the templates that define them are updated or new solver card support is added.

There are several different types of attributes including array, double, entity, integer and string. Each of these types is handled in a similar fashion to the examples below. The difference is that each entity type uses an appropriate *attributeupdate command based on its type. There are also a number of hm_attribute commands to query entity attributes.

Solver Attributes and Card Images

A sample card image for an OptiStruct MAT1 material collector in the Property Editor is shown below.
Figure 1.

For each field in the above dialog there is a corresponding attribute and data name in the OptiStruct template. An excerpt is shown below for several of the card image fields:
*defineattribute(E,1,real,none)
*defineattribute(G,2,real,none)
*defineattribute(Nu,3,real,none)
*defineattribute(Rho,4,real,none)

The first argument in the *defineattribute command is the solver data name. The second is the attribute ID and the third is the attribute type. There are 11 different attribute types. Attributes of different types are created and updated with different commands, but the overall concept is the same.

Each attribute in the template has a definition similar to these. Additionally, there are card image definitions that define how the card editor is generated inside of HyperMesh for each attribute. An excerpt of the OptiStruct MAT1 card image is shown below:
*menustring("MAT1    ")
*menufield(ID,integer,id,8)
    *menufield(E,real,$E,8)
    *menudefaultvalue("        ")
    *menuinitialvalue(210000.0)
    *menurestrictedvalue(>,0.0)
*menufield(G,real,$G,8)
    *menudefaultvalue("        ")
    *menuinitialvalue(80769.2)
    *menurestrictedvalue(>,0.0)
*menufield(NU,real,$Nu,8)
    *menudefaultvalue("        ")
    *menurestrictedvalue(>,-1.0)
    *menurestrictedvalue(<,0.5)
    *menuinitialvalue(0.3)
*menufield(RHO,real,$Rho,8)
    *menudefaultvalue("        ")
    *menuinitialvalue(7.85e-09)
Notice the *menufield command used above. This command determines how a field is created in the Card Editor for a particular attribute. The first argument is the text string to show above the data field and the third argument is the particular data name that is associated with that field. For example, the attribute and card image definitions for the Young’s Modulus for the MAT1 material are:
*defineattribute(E,1,real,none)
*menufield(E,real,$E,8)

Knowing all of this information allows you to assign, update and query the data.

Assigning Data to Solver Attributes

It is easiest to understand how to assign data to solver attributes with a specific example. When the MAT1 material collector shown above is initially created, the relevant commands to assign values to its attributes are written to the command.tcl file. Note that the values correspond to those shown in the figure above:
*collectorcreate materials "steel" "" 11;
*createmark materials 2 "steel";
*dictionaryload materials 2 "C:/Program Files/Altair/14.0/templates/feoutput/optistruct/optistruct" "MAT1";
*attributeupdateint materials 1 3240 1 2 0 1;
*attributeupdatedouble materials 1 1 1 1 0 210000;
*attributeupdatedouble materials 1 2 1 0 0 0;
*attributeupdatedouble materials 1 3 1 1 0 0.3;
*attributeupdatedouble materials 1 4 1 1 0 7.85e-009;
*attributeupdatedouble materials 1 5 1 0 0 0;
*attributeupdatedouble materials 1 6 1 0 0 0;
*attributeupdatedouble materials 1 7 1 0 0 0;
*attributeupdatedouble materials 1 341 1 0 0 0;
*attributeupdatedouble materials 1 343 1 0 0 0;
*attributeupdatedouble materials 1 345 1 0 0 0;
*attributeupdateint materials 1 5237 1 2 0 0;
Each of these commands sets one of the MAT1 attributes either to its default value or to the user defined value. The third argument in the *attributeupdateint and *attributeupdatedouble commands is the attribute ID. For example:
*attributeupdatedouble materials 1 1 1 1 0 210000

Looking at the OptiStruct template, attribute 1 corresponds to the data name E, or Young’s Modulus.

Simply running these commands as-is is not very flexible. The material ID, name and values are all hard coded. The template file location in the *dictionaryload command is also hard coded. Finally, there are a lot of extra commands that set attributes that aren’t necessary.

Creating a Reusable and Modular Procedure

In order to make this more flexible, you can create a Tcl procedure that allows you to substitute variables for the name, color and data values. You can also make the template file path modular across different platforms and make the material ID a variable that references the newly created material ID so the *attributeupdatedouble and *attributeupdateint commands work properly.
proc mat_create { name color E Nu Rho } {
    if {[hm_entityinfo exist mats $name -byname] == 1} {
        hm_errormessage "Material $name already exists"
        return;
    } else {
        *collectorcreate materials "$name" "" $color;
        *createmark materials 2 "$name";
        #Retrieve material ID for use below;
        set mat_id [hm_getmark mats 2];
        *dictionaryload materials 2 "[file normalize [hm_info exporttemplate]]" "MAT1";
        *attributeupdateint materials $mat_id 3240 1 2 0 1;
        *attributeupdatedouble materials $mat_id 1 1 1 0 $E;
        *attributeupdatedouble materials $mat_id 3 1 1 0 $Nu;
        *attributeupdatedouble materials $mat_id 4 1 1 0 $Rho;
        return;
    }
}

The advantage of doing this is that mat_create is now modular. The developer need only pass the material name, color and the values for the material properties and the procedure will create the material accordingly.

Updating Solver Attributes

In addition to creating a card image from scratch, it is also possible to update an existing card image. A procedure to do this is almost identical to the procedure to create a new image, with the exception that the material is not created and thus the procedure requires a material ID to be passed instead of a material name.
proc mat_update { mat_id E Nu Rho } {
    if {[hm_entityinfo exist mats $mat_id -byid] == 0} {
        hm_errormessage "Material $mat_id does not exist"
        return;
    } else {
        *createmark materials 2 "by id" "$mat_id";
        *dictionaryload materials 2 "[file normalize [hm_info exporttemplate]]" "MAT1";
        *attributeupdatedouble materials $mat_id 1 1 1 0 $E;
        *attributeupdatedouble materials $mat_id 3 1 1 0 $Nu;
        *attributeupdatedouble materials $mat_id 4 1 1 0 $Rho;
        return;
    }
}

Make sure to pay close attention to the information you wish to update, and update only those fields. In this example, the comment options are not of particular interest for this procedure, so attribute 3240 is not updated.

Querying Solver Attributes

In addition to the standard HyperMesh data names, data names also refer to solver specific attributes as described above. Solver data names are accessed similarly to HyperMesh data names, using the hm_getvalue command.

These commands use a data_name_string to access a particular piece of data. As noted above, each attribute has both an ID and a data name. For example, from the MAT1 material card there are several attributes of interest:
*defineattribute(E,1,real,none)
*defineattribute(Nu,3,real,none)
*defineattribute(Rho,4,real,none)
Again, the first argument is the solver data name and the second is the attribute ID. So in order to extract the value of E from a material with ID 11:
hm_getvalue mats id=11 dataname=E
Below is a procedure to extract the data from a MAT1 card image and show the values in the HyperMesh status bar:
proc mat_query { mat_id } {
    if {[hm_entityinfo exist mats $mat_id -byid] == 0} {
        hm_errormessage "Material $mat_id does not exist"
        return;
    } else {  
        set E [hm_getvalue materials id=$mat_id dataname=E];
        set Nu [hm_getvalue materials id=$mat_id dataname=Nu];
        set Rho [hm_getvalue materials id=$mat_id dataname=Rho];
        hm_usermessage "E=$E Nu=$Nu Rho=$Rho"
    }
}