Where We Left Off Last Time…
In the second part of this series I left you with a recipe for discovering ANSYS Mechanical functionality by using entities in the GUI itself to help guide your search through the ANSYS source code that is shipped with every ANSYS Mechanical installation. This technique is the first tool in our toolbox. In this blog post, I’ll introduce you to a couple of the internal ANSYS Mechanical data structures that are associated with geometry in particular. I’ll simply be introducing them in this blog without any discussion of how one might determine additional functionality associated with these structures. In a future blog post, I’ll step you through the use of the most powerful tool available in our toolbox: the Visual Studio Script Debugger.
Introducing the ANSYS Mechanical Geometry Selection Manager and B-Rep Geometry Data Structure
CAD geometry is represented inside a computer using a Boundary Representation (B-Rep) data structure. This data structure falls into a category of data structures computer scientists like to call graphs. In general, a graph is a structure comprised of nodes connected to each other with arcs. A road map is a type of graph where cities represent nodes and the roads connecting them represent arcs. Sites like facebook and linkedin are giant graphs where people are represented as nodes and friendships or acquaintances are represented as arcs. As you can see, graphs are pretty general and you can represent lots of structured relationships with them.
In CAD geometry, the nodes in our graph are comprised of various topological entities like vertices, edges, faces, shells and bodies. The arcs are the incident relationships that exist between these entities. So, for example, an edge will have a start vertex and an end vertex. These relationships can be represented by links between the particular edge and its start vertex or end vertex. Likewise, however, the particular start vertex of one edge may be the end vertex of another edge. So, this relationship can be represented by links between a given vertex and all of the edges to which it is attached. There are similar relationships between edges and faces. A series of edges will form the boundary for a given face and a series of faces might share a common edge. Shells represent a volume that is defined by a set of connected faces. (i.e faces that share common edges) A body is comprised of one or more shells. Why isn’t a body the same as a shell? Well, it turns out that bodies with internal holes are more conveniently represented as comprising of two or more shells. One shell represents the outermost envelope and the other shells represent the internal voids. How, then, does one know if they are inside or outside of a body? Well, the faces that comprise a shell each have an associated outward normal vector that points to the “outside” of the body in question. The normal vector sense is defined using an ordering on the bounding edges of a given face. Typically as you traverse the list of edges comprising the boundary of a given face, you are actually walking counter-clockwise around the face. Using this assumption, one can determine an outward normal.
Lets discuss some of the specifics of the ANSYS Mechanical B-Rep. First, an individual B-Rep structure is associated with each part in a Mechanical session. So, if you have 15 parts you will have 15 different B-Rep structures. Second, each entity (vertex, edge, face, body) within a given B-Rep has an associated unique ID. (This ID is called the TopoID, or Topological ID) This ID is just an unsigned integer value, with one small twist. The top two bits of the ID encode the entity’s topological type. That is, if you stripped off the top two bits, you would get one of the following four combinations:
Top Two Bits
The lower 30 bits actually encode the unique id for a given vertex, edge, face or body. So, what that means is that ANSYS Mechanical is limited to geometry with fewer than roughly one billion vertices, edges, etc… If you have a model with more than that, perhaps a bit of geometry simplification is in order.
To access a given topological entity within a B-Rep object, one uses the following type of function call (Note, I haven’t introduced where the brep_object below comes from… Bear with me, we’ll get to it soon.)
var topo_object = brep_object.Cell(topo_id);
The Cell function accepts a valid topoID and returns the associated object. The returned object is a rich object and has numerous fields that obviously differ depending on the topological type. So, for example, an edge object will have a StartVertex and EndVertex field that contains references to its start and end vertices in particular. However, all topological objects have one field in common. They all contain an ID field. So the following code would supply the topolD of the start vertex associated with a given edge:
var brep_object = /*Get B-Rep from somewhere */ var edge_id = /* Get Edge ID from somewhere*/ var edge = brep_object.Cell(edge_id); var start_vertex_id = edge.StartVertex.Id;
You might gather that one can get the actual start vertex object with a subsequent line like:
var start_vertex = brep_object.Cell(start_vertex_id);
Now, each vertex object is going to contain a list of edges that are attached to this vertex. So, if we needed all the edges attached to the original edge for some reason, we could use this technique with the start vertex and the end vertex.
Walking the B-Rep data structure is perhaps interesting at best, but it currently doesn’t do anything for us. What we need is to be able to select some piece of geometry, or pieces of geometry. Enter the ANSYS Mechanical Selection Manager. This object is closely associated with the B-Rep data structures. Before we discuss this object in some detail, consider starting each and every one of your scripts with the following code:
The second global variable shown above is the selection manager, or SM. You can see that this object is a child of the script code object. This object has numerous functions and properties and in a later post I hope to document as many as I can. However, a great deal of mileage can be gained by understanding the following two function calls, and the following few properties. I list them below in code form so you can see how they would typically be called inside a script:
/* F U N C T I O N S O F T H E S E L E C T I O N M A N A G E R */ // Clear() // This function resets the selection manager so that no geometry is currently // selected. SM.Clear(); // AddToSelection(partID, topoID, bShouldDraw) // This function adds a particular topological entity (vertex, edge, face, body) // to the currently selected set. The first argument specifies the particular // part this entity is associated with. You can think of this as referencing the // particular BRep structure. The second argument specifies the topological // entities specific ID. The final argument is a boolean specifying whether or // not the selection manager should highlight the selected geometry in green. SM.AddToSelection(partID, topoID, bShouldDraw); /* P R O P E R T I E S O F T H E S E L E C T I O N M A N A G E R */ // Vertices // The number of currently selected vertices var num_selected_vertices = SM.Vertices; // Edges // The number of currently selected edges. var num_selected_edges = SM.Edges; // Faces // The number of currently selected faces. var num_selected_faces = SM.Faces // Parts // The number of currently selected (bodies*) // Note: I think this is where the SM and the BRep use different // terms for a body. However, I may be wrong. var num_selected_bodies = SM.Parts // SelectedCount // The total number of selected entities. (Sum of the above) var num_selected = SM.SelectedCount; // SelectedEntityTopoID(i) // The ith selected entity's topological id. Note you can use the // top two bits of this id to determine the type of this selected // object. i goes from 1 to SelectedCount. var selected_topoid = SM.SelectedEntityTopoID(i); // SelectedPartID(i) // The part id for the ith selected entity. For models with numerous // parts this will tell you which part the currently selected entity is // associated with. You use this to reference the proper BRep structure. // i goes from 1 to SelectedCount. var selected_partid = SM.SelectedPartID(i); // PartMgr // The Part Manager (PartMgr) object is a child of the selection manager. // It also has numerous methods and properties, however, the one // property that I have found most useful is the PartById(id). // PartMgr.PartById(id) // This returns the particular part object associated with a given part id var part = SM.PartMgr.PartById(partID); // The part object returned by the PartMgr.PartById(partID) call has // associated with it a given BRep data structure. Referencing this brep // structure is how you get from the selection manager's selected entity // id to a given piece of topology. So for example, assume the user // has selected one face in the model. This is one way we can get to that // face object. var topo_id = SM.SelectedEntityTopoID(1); var part_id = SM.SelectedPartID(1); var part = SM.PartMgr.PartById(part_id); var brep = part.BRep; var face = brep.Cell(topo_id);
The above code represents a small portion of the interface of the ANSYS Mechanical selection manager and also the geometry B-Rep structure. As you can see, the two structures are coupled through the notion of a part id, which selects a given B-Rep structure, and a selected entity id, which represents a piece of topology within the specified B-Rep structure. Once a given topological entity is identified and retrieved from the B-Rep structure, one can navigate the connectivity information contained in the B-Rep to find other topological entities nearby. By using a combination of the Clear() function and the AddToSelection(…) function associated with the selection manager, one can programmatically control which topological entities are currently selected.
You can see this technique in action by perusing the Example in the previous posting.