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
*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.
*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)
*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
*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;
*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
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
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.
*defineattribute(E,1,real,none)
*defineattribute(Nu,3,real,none)
*defineattribute(Rho,4,real,none)
hm_getvalue mats id=11 dataname=E
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"
}
}