Nastran Analysis Interface Module (AIM)
Natran Analysis Interface Module (AIM)
Nastran AIM Examples

This section introduces the user to the Nastran AIM via examples. These examples are intended to introduce the user to nastran functionality. They make use of the information found in the AIM Inputs, AIM Outputs and Nastran AIM attributes sections.

Single Load Case Example

The first example is a simple three bar truss structure. This example is intended to demonstrate the use of all the attributes in addition to introducing the user to the Nastran AIM.

threeBar.png
Three Bar Truss

The follow code details the process in a *.csm file that generates a three bar truss. Note to execute in serveCSM a dictionary file must be included

First step is to define the analysis intent that the geometry is intended support.

attribute capsIntent STRUCTURE

Next we will define the design parameters to define the wing cross section and planform. Notice that the despmtr entries have a dimension input that must be defined for inputs with a length greater than one.

dimension X 1 4 1
dimension Y 1 4 1
dimension Z 1 4 1
despmtr X "-10; 0; 10; 0;"
despmtr Y " 0; 0; 0; -10;"
despmtr Z " 0; 0; 0; 0;"

Next the three bar truss is defined using the points defined in the despmtr entries. Notice that the middle edge is "drawn" twice. This is done because OpenCASCADE cannot perform boolean operations on non-manifold (not closed) wire bodies.

skbeg X[1,1] Y[1,1] Z[1,1]
linseg X[1,4] Y[1,4] Z[1,4]
linseg X[1,2] Y[1,2] Z[1,2]
linseg X[1,4] Y[1,4] Z[1,4]
linseg X[1,3] Y[1,3] Z[1,3]
skend

In this section the edge elements are attributed with a capsGroup string $bar1 etc. so information can be assigned to them. Notice the capsIgnore attribute assigned to one of the overlapping "middle" edges defined in the geometry above. The reason for this is discussed in the Nastran AIM attributes section.

select edge 1
attribute capsGroup $bar1
select edge 2
attribute capsGroup $bar2
select edge 3
attribute capsIgnore $multipleEdge
select edge 4
attribute capsGroup $bar3

Finally, the nodes are attributed. In this case, the three nodes across the top are given the same capsConstraint name. They could be assigned a different name allowing the user to define a different boundary condition at each location. The lower node is given a different capsLoad name so a load can be applied.

select node 1
attribute capsConstraint $boundary
select node 2
attribute capsLoad $force
select node 3
attribute capsConstraint $boundary
select node 4
attribute capsConstraint $boundary

The following input defines a pyCAPS input that can be used along with the above *.csm input to create a nastran input. First the pyCAPS and os module needs to be imported.

# Import pyCAPS class file
from pyCAPS import capsProblem
# Import os module
try:
import os
except:
print ("Unable to import os module")
raise SystemError

Note if your Python major version is less than 3 (i.e. Python 2.7) the following statement should also be included so that print statements work correctly.

from __future__ import print_function

Once the modules have been loaded the problem needs to be initiated.

# Initialize capsProblem object
myProblem = capsProblem()

Next the *.csm file is loaded. Though not shown in this example the user has access to the X, Y and Z despmtr inputs from this pyCAPS script.

# Load CSM file
myProblem.loadCAPS("./csmData/feaThreeBar.csm")

The Nastran AIM is then loaded with the capsIntent set to STRUCTURE (this is consistent with the intent specified above in the *.csm file.

# Load nastran aim
nastranAIM = myProblem.loadAIM(aim = "nastranAIM",
altName = "nastran",
analysisDir= "NastranThreeBar",
capsIntent = "STRUCTURE")

After the AIM is loaded some of the inputs to the AIM are defined. A full list of options can be found in the AIM Inputs section. In this case the Proj_Name is entered. The project name becomes the Nastran input file names. Two are create projectName.bdf and projectName.dat. The *.bdf file contains the grid and connectivity information. The data file contains the case control and other bulk data inputs required by Nastran. The input format is selected as Free and large field format is used when the option is available. This is most likely in the GRID entries only. Additionally the analysis type selected is Static. The maximum and minimum points that can be placed along an edge is set to be two. This ensures that each edge shown in the figure will be represented by a single finite element bar.

# Set project name so a mesh file is generated
projectName = "threebar_nastran_Test"
nastranAIM.setAnalysisVal("Proj_Name", projectName)
nastranAIM.setAnalysisVal("File_Format", "Free")
nastranAIM.setAnalysisVal("Mesh_File_Format", "Large")
nastranAIM.setAnalysisVal("Edge_Point_Max", 2);
nastranAIM.setAnalysisVal("Edge_Point_Min", 2);
nastranAIM.setAnalysisVal("Analysis_Type", "Static");

Next the material inputs, property selection, constraints and loads are defined. First materials are defined.

madeupium = {"materialType" : "isotropic",
"youngModulus" : 1.0E7 ,
"poissonRatio" : .33,
"density" : 0.1}
nastranAIM.setAnalysisVal("Material", [("Madeupium", madeupium)])

Next these materials are used in the property definition. In this case two bar type properties are assigned to the edges. The outer bars have a property with a different area then the center bar. Note the relationship of bar1 etc. between this pyCAPS input and the *,csm input previously shown.

rod = {"propertyType" : "Rod",
"material" : "Madeupium",
"crossSecArea" : 1.0}
rod2 = {"propertyType" : "Rod",
"material" : "Madeupium",
"crossSecArea" : 2.0}
nastranAIM.setAnalysisVal("Property", [("bar1", rod),
("bar2", rod2),
("bar3", rod)])

Next the three nodes with capsConstraint boundary are constrained in all six degrees of freedom.

constraint = {"groupName" : ["boundary"],
"dofConstraint" : 123456}
nastranAIM.setAnalysisVal("Constraint", ("BoundaryCondition", constraint))

Finally a load is applied the the node with the capsLoad force.

load = {"groupName" : "force",
"loadType" : "GridForce",
"forceScaleFactor" : 20000.0,
"directionVector" : [0.8, -0.6, 0.0]}
nastranAIM.setAnalysisVal("Load", ("appliedForce", load ))

Finally an analysis case is defined that connects an analysis type to the load and constraint condition by name.

value = {"analysisType" : "Static",
"analysisConstraint" : "BoundaryCondition",
"analysisLoad" : "appliedForce"}
myProblem.analysis["nastran"].setAnalysisVal("Analysis", ("SingleLoadCase", value ))

Once all the inputs have been set, aimPreanalysis needs to be executed. During this operation all the necessary files to run Nastran are generated and placed in the analysis working directory (analysisDir)

nastranAIM.aimPreAnalysis()

An OS system call is then made from Python to execute Nastran.

print ("\n\nRunning Nastran......")
currentDirectory = os.getcwd() # Get our current working directory
os.chdir(nastranAIM.analysisDir) # Move into test directory
os.system("nastran old=no notify=no batch=no scr=yes sdirectory=./ " + projectName + ".dat"); # Run Nastran via system call
os.chdir(currentDirectory) # Move back to working directory
print ("Done running Nastran!")

A call to aimPostanalysis is then made to check to see if AVL executed successfully and the expected files were generated.

nastranAIM.aimPostAnalysis()

Finally the session is closed

myProblem.closeCAPS()

Multiple Load/Boundary Case Example

To create multiple load cases with different boundary conditions the pyCAPS input for constraints, and loads changes with respect to the Single Load Case Example. In addition an analysis section is added.

The constraint section may expand to allow multiple boundary conditions. In this way each load case can have a seperate boundary condition. If the input is left identical to the single load case example then the same boundary condition will be applied to each load case.

constraints = []
constraint = {"groupName" : ["boundary"],
"dofConstraint" : 123456}
tmp = ( "conOne", constraint )
constraints.append( tmp )
constraint = {"groupName" : ["boundary"],
"dofConstraint" : 123}
tmp = ( "conTwo", constraint )
constraints.append( tmp )
nastranAIM.setAnalysisVal("Constraint", constraints)

Notice that an empty constraints variable has been defined. Then a tmp tuple is created with the name "conOne" paired with the dictionary constraint. This tuple is appended to the empty constraints variable. The process is repeated for the second boundary condition. Then the AIM input "Constraint" is defined with the information.

Next the load input is expanded to contain multiple cases.

loads = []
load = {"groupName" : "force",
"loadType" : "GridForce",
"forceScaleFactor" : 20000.0,
"directionVector" : [0.8, -0.6, 0.0]}
loads.append( ("loadOne", load) )
load = {"groupName" : "force",
"loadType" : "GridForce",
"forceScaleFactor" : 20000.0,
"directionVector" : [-0.8, -0.6, 0.0]}
loads.append( ("loadTwo", load) )
nastranAIM.setAnalysisVal("Load", loads)

The process is identical to the constraint input.

Finally, analysis cases are defined that connect an analysis type to a load and constraint condition by name.

analysisCases = []
value = {"analysisType" : "Static",
"analysisConstraint" : "conOne",
"analysisLoad" : "loadOne"}
analysisCases.append( ("analysisOne", value ) )
value = {"analysisType" : "Static",
"analysisConstraint" : "conTwo",
"analysisLoad" : "loadTwo"}
analysisCases.append( ("analysisTwo", value ) )
myProblem.analysis["nastran"].setAnalysisVal("Analysis", analysisCases)

Notice how the tuple names "conOne", "loadOne" and "analysisOne" are all tied together. The "analysisOne" string also becomes the case control LABEL for the load case in the Nastran input file.

To finish the pyCAPS input the process starting with the pre-analysis input is identical to the Single Load Case Example input.

Modal Analysis Example Case

To create input for a modal analysis a two simple changes are required to the Single Load Case Example input. The first change is to the AIM Inputs Analysis_Type. This input is the last input in the list below.

# Set project name so a mesh file is generated
projectName = "threebar_nastran_Test"
nastranAIM.setAnalysisVal("Proj_Name", projectName)
nastranAIM.setAnalysisVal("File_Format", "Free")
nastranAIM.setAnalysisVal("Mesh_File_Format", "Large")
nastranAIM.setAnalysisVal("Edge_Point_Max", 2);
nastranAIM.setAnalysisVal("Edge_Point_Min", 2);
nastranAIM.setAnalysisVal("Analysis_Type", "Modal");

A description of each of these inputs can be found in Single Load Case Example.

The second change is replacing the load case information with a definition for the Analysis AIM input.

eigen = { "extractionMethod" : "Lanczos",
"frequencyRange" : [0, 10000],
"numEstEigenvalue" : 1,
"numDesiredEigenvalue" : 10,
"eigenNormaliztion" : "MASS"}
nastranAIM.setAnalysisVal("Analysis", ("EigenAnalysis", eigen))

This information defines the eigenvalue solver method and parameters and assigns it as an analysis case.

Optimization Example Case

This section creates a design model out of the single load case example. The first change is an update to the Analysis_Type AIM Input to StaticOpt.

# Set project name so a mesh file is generated
projectName = "threebar_nastran_Test"
nastranAIM.setAnalysisVal("Proj_Name", projectName)
nastranAIM.setAnalysisVal("File_Format", "Free")
nastranAIM.setAnalysisVal("Mesh_File_Format", "Large")
nastranAIM.setAnalysisVal("Edge_Point_Max", 2);
nastranAIM.setAnalysisVal("Edge_Point_Min", 2);
nastranAIM.setAnalysisVal("Analysis_Type", "StaticOpt");

The next update adds a material allowable to the material input yieldAllow. This is not a requirement for THIS optimization problem, but this input is referenced when design constraints are added later.

madeupium = {"materialType" : "isotropic",
"youngModulus" : 1.0E7 ,
"poissonRatio" : .33,
"density" : 0.1,
"yieldAllow" : 5.6E7}
nastranAIM.setAnalysisVal("Material", [("Madeupium", madeupium)])

The first large optimization input is the design variable definition section. For more information, the user is pointed to the FEA DesignVariable section. In this section the area of each rod element in the three bar truss is defined as a separate design variable. Finally each of these variables are used to defined AIM Input Design_Variable

DesVar1 = {"groupName" : "bar1",
"initialValue" : rod["crossSecArea"],
"lowerBound" : rod["crossSecArea"]*0.5,
"upperBound" : rod["crossSecArea"]*1.5,
"maxDelta" : rod["crossSecArea"]*0.1,
"fieldName" : "A"}
DesVar2 = {"groupName" : "bar2",
"initialValue" : rod2["crossSecArea"],
"lowerBound" : rod2["crossSecArea"]*0.5,
"upperBound" : rod2["crossSecArea"]*1.5,
"maxDelta" : rod2["crossSecArea"]*0.1,
"fieldName" : "A"}
DesVar3 = {"groupName" : "bar3",
"initialValue" : rod["crossSecArea"],
"lowerBound" : rod["crossSecArea"]*0.5,
"upperBound" : rod["crossSecArea"]*1.5,
"maxDelta" : rod["crossSecArea"]*0.1,
"fieldName" : "A"}
myProblem.analysis["nastran"].setAnalysisVal("Design_Variable", [("Bar1A", DesVar1),
("Bar2A", DesVar2),
("Bar3A", DesVar3)])

The next unique section is the addition of design constraints. In this problem stress constraints in each rod element are added.

designConstraint1 = {"groupName" : "bar1",
"responseType" : "STRESS",
"lowerBound" : -madeupium["yieldAllow"],
"upperBound" : madeupium["yieldAllow"]}
designConstraint2 = {"groupName" : "bar2",
"responseType" : "STRESS",
"lowerBound" : -madeupium["yieldAllow"],
"upperBound" : madeupium["yieldAllow"]}
designConstraint3 = {"groupName" : "bar3",
"responseType" : "STRESS",
"lowerBound" : -madeupium["yieldAllow"],
"upperBound" : madeupium["yieldAllow"]}
myProblem.analysis["nastran"].setAnalysisVal("Design_Constraint",[("stress1", designConstraint1),
("stress2", designConstraint2),
("stress3", designConstraint3)])

This completes the unique parts of the design inputs required for a Nastran optimization problem.

Composite Wing Example

This example introduces the use of composite materials. Initially a composite wing frequency analysis is completed. This example will grow to introduce design optimization with composites, including design variable linking.

compositeWing.png
Composite Wing Example

First step is to define the analysis intent that the geometry is intended support. In this case the intent is STRUCTURE.

attribute capsIntent STRUCTURE

The parameter being set in this case is a definition for a coordinate system in Engineering Sketch Pad. The documentation for csystem inputs is as follows.

CSYSTEM   $csysName csysList
        use:    attach a Csystem to Body on top of stack
        pops:   any
        pushes: any
        notes:  Sketch may not be open
                if     csysList contains 9 entries:
                   {x0, y0, z0, dx1, dy1, dz1, dx2, dy2, dz2}
                   origin is at (x0,y0,q0)
                   dirn1  is in (dx1,dy1,dz1) direction
                   dirn2  is part of (dx2,dy2,dz2) that is orthog. to dirn1
                elseif csysList contains 5 entries and first is positive
                   {+iface, ubar0, vbar0, du2, dv2}
                   origin is at normalized (ubar0,vbar0) in iface
                   dirn1  is normal to Face
                   dirn2  is in (du2,dv2) direction
                elseif csysList contains 5 entries and first is negative
                   {-iedge, tbar, dx2, dy2, dz2}
                   origin is at normalized (tbar) in iedge
                   dirn1  is tangent to Edge
                   dirn2  is part of (dx2,dy2,dz2) that is orthog. to dirn1
                elseif csysList contains 7 entries
                   {inode, dx1, dy1, dz1, dx2, dy2, dz2}
                   origin is at Node inode
                   dirn1  is in (dx1,dy1,dz1) direction
                   dirn2  is part of (dx1,dy2,dz2) that is orthog. to dirn1
                else
                   error
                semicolon-sep lists can instead refer to
                   multi-valued Parameter
                dirn3 is formed by (dirn1)-cross-(dirn2)
                does not create a Branch

In the compositesys parameter defined below 9 entries are given. Based on the documentation above this indicates the following.

Origin 0.0 5.5 0.0
Vector along x-Axis 79.3685 -0.65432 0.0
Vector along y-Axis 0.65432 79.3685 0.0

It should be noted that the vector along the y-axis may not be input perfectly perpendicular to the vector along the x-Axis. In this case ESP takes the projection of the input vector that is in the plane defined by both input vectors and perpendicular to the x-Axis. This is the case for all csystem input options defined above.

dimension compositesys 9 1 0
set compositesys 0;5.5;0;79.3685;-0.65432;0;0.65432;79.3685;0

The geometry definition was generated by the ESP sketcher. Users are referred to ESP tutorials for information on how to create a sketch. The result is copy and pasted into the *.csm file snippet shown below.

skbeg 0 0 0 1
skvar xy -0.024750;0.051384;4.841311;-0.024750;-3.895337;0.000000;82.067045;-3.895337;0.000000;77.594095;3.314007;0.000000;4.132462;13.891219;0.000000;-2.340160;13.680727;0.000000;-1.235078;10.891711;0.000000;
skcon X 1 -1 0
skcon Y 1 -1 0
skcon V 1 2 0
skcon L 3 4 8.5
skcon R 7 1 5.5
skcon H 2 3 0
skcon L 1 2 3.91
skcon L 6 7 3
skcon L 5 6 6.5
skcon L 4 5 74.2
skcon L 2 3 82.1
skcon P 1 -1 0
skcon A 5 -1 10
skcon A 6 -1 110
skcon A 4 -1 50
linseg ::x[2] ::y[2] 0
linseg ::x[3] ::y[3] 0
linseg ::x[4] ::y[4] 0
linseg ::x[5] ::y[5] 0
linseg ::x[6] ::y[6] 0
linseg ::x[7] ::y[7] 0
arc ::x[1] ::y[1] 0 ::d[1] xy
skend 0

The root edges are marked as capsConstraint locations. The overall surfaces is given a capsGroup and capsLoad attribute and a csystem definition is attached to it using the compositesys parameter previously discussed.

attribute capsGroup $wing
attribute capsLoad $wing
attribute capsBound $wing
csystem wing compositesys
select edge 7
attribute capsConstraint $root
select edge 6
attribute capsConstraint $root
select edge 1
attribute capsConstraint $root

This model was created in centimeters and is converted to inches.

scale 1/2.54

Note if your Python major version is less than 3 (i.e. Python 2.7) the following statement should also be included so that print statements work correctly.

The following input defines a pyCAPS input that can be used along with the above *.csm input to create a nastran input. First the pyCAPS and os module needs to be imported.

Once the modules have been loaded the problem needs to be initiated.

Next the *.csm file is loaded. Though not shown in this example the user has access to the X, Y and Z despmtr inputs from this pyCAPS script.

The Nastran AIM is then loaded with the capsIntent set to STRUCTURE (this is consistent with the fidelity specified above in the *.csm file.

After the AIM is loaded some of the inputs to the AIM are defined. A full list of options can be found in the AIM Inputs section. In this case the Proj_Name is entered. The project name becomes the Nastran input file names. Two are create projectName.bdf and projectName.dat. The *.bdf file contains the grid and connectivity information. The data file contains the case control and other bulk data inputs required by Nastran. The input format is selected as Small and Large field format is used when the option is available. This is most likely in the GRID entries only. Additionally, the analysis type selected is Static. The maximum points that can be placed along an edge is set to be 40.

In this example two materials are defined. This demonstrates how simple it is to change materials in a model. Both an aluminum and Graphite_expoxy material are defined in the Material AIM Inputs.

Again property information is defined for both an aluminum and composite stack version of the model. However, only the composite entry is defined in the Property AIM Inputs.

The composite definition brings together the materials in each layer of the stack, their thicknesses and orientations. For the sequence defined below the order of the sequence is given in the table below. The full sequence is given to point out that they symmetry condition is applied to the right side of the compositeOrientation input.

0000-4545-454545-4545-450000

Finally, the property is assigned to the regions with the capsGroup $wing attribute.

In this example the root edges are constrained in all degrees of freedom. This constraint references the capsConstraint $root input defined in the *.csm file.

As previously shown in Modal Analysis Example Case information to define an eigen value problem is entered and the Analysis AIM Input is defined.

Finally, preAnalysis is executed to generate all the required Nastran inputs.

Nastran is executed with a simple system call.

A post analysis command is entered allowing the user to access output data, if desired, from the application.

The caps session is closed.

Composite Wing Optimization Example

This section removes the frequency analysis and adds a pressure load to the previously introduced composite wing example case. Then An optimization problem allowing the thickness of each ply layer to change is performed.