Geometry selection

getByBounding...(...)

Vertices, edges, faces and cells are stored in respective sequences having the methods:

  • <sequence>.getByBoundingBox(xMin, yMin, zMin, xMax, yMax, zMax)
  • <sequence>.getByBoundingCylinder(center1, center2, radius)
  • <sequence>.getByBoundingSphere(center, radius)

A layered solid structure with a quarter of a hole and was generated by the following script:

In [ ]:
from abaqus import *
from abaqusConstants import *

def createPart(modelname, L, b, t, r, n):
    mod = mdb.Model(name=modelname)
    ske = mod.ConstrainedSketch(name='__profile__', sheetSize=200.0)
    session.viewports['Viewport: 1'].setValues(displayedObject=ske)
    ske.ArcByCenterEnds(center=(0,0), point1=(0,r), point2=(r,0), direction=CLOCKWISE)
    ske.Line(point1=(r, 0.0), point2=(L, 0.0))
    ske.Line(point1=(L, 0.0), point2=(L, b))
    ske.Line(point1=(L, b), point2=(0.0, b))
    ske.Line(point1=(0.0, b), point2=(0.0, r))
    prt = mod.Part(name='P1', dimensionality=THREE_D, type=DEFORMABLE_BODY)
    prt.BaseSolidExtrude(sketch=ske, depth=t)
    del ske
    tk = t/float(n)
    prt.DatumCsysByDefault(coordSysType=CARTESIAN)
    zpos=tk
    for i in range(0, n-1):
        id=prt.DatumPlaneByPrincipalPlane(principalPlane=XYPLANE, offset=zpos).id
        prt.PartitionCellByDatumPlane(datumPlane=prt.datums[id], cells=prt.cells)
        zpos=zpos+tk
    session.viewports['Viewport: 1'].setValues(displayedObject=prt)

createPart(modelname='M1', L=100.0, b=50.0, t=20.0, r=25.0, n=5)

Selecting geometry

Access to the part:

>>> prt = mdb.models['M1'].parts['P1']

The number of faces in the part is

>>> len(prt.faces)
31

and the number of faces returned by getByBoundingBox() with no arguments, is identical, implying that the default values of minimum and maximum coordinates are the extreem values:

>>> f1 = prt.faces.getByBoundingBox()
>>> len(f1)
31

Selecting the faces at y=0 can be achived by using only one limit:

>>> f2 = prt.faces.getByBoundingBox(yMax=0)
>>> prt.Set(name='faces at y=0', faces=f2)

The face at y=0 and half way between the top and bottom:

>>> f3 = prt.faces.getByBoundingBox(yMax=0, zMin=8, zMax=12)
>>> prt.Set(name='faces at y=0 mid', faces=f3)

Observe that the whole entety must be inside the bounding box for it to be included in the selection. The following parameters will return only the single face as in the previous example, although the bounding box spans most of the adjacent faces (but not the full span):

>>> f3 = prt.faces.getByBoundingBox(yMax=0, zMin=4.1, zMax=15.9)
>>> prt.Set(name='faces at y=0 mid', faces=f3)

All edges at the hole using getByBoundingBox():

>>> e1 = prt.edges.getByBoundingBox(xMax=25,yMax=25)
>>> prt.Set(name='edges hole', edges=e1)

Selecting only the circular edges in one operation is not possible by the getBy... methods. However, a single circular edge can be retrived by for instance (the bottom circular edge):

>>> e2 = prt.edges.getByBoundingBox(xMax=25,yMax=25,zMin=0-0.1,zMax=0+0.1)
>>> [e.index for e in e2]
[44]

Hence, a loop will complete the task. Initially, an empty sequence of the correct type is instanciated from the prt.edges sequence. Individual edges are then added using getByBoundingBox():

>>> e3 = prt.edges[0:0] # empty sequence
>>> for z in [0,4,8,12,16,20]:
...     e3 = e3 + prt.edges.getByBoundingBox(xMax=25,yMax=25,zMin=z-0.1,zMax=z+0.1)
>>> prt.Set(name='edges hole circular', edges = e3)

Edges, faces and vertices at the hole can also be selected using getByBoundingCylinder(). Different from getByBoundingBox(), the arguments are not optional:

>>> f4 = prt.faces.getByBoundingCylinder(center1=(0,0,0), center2=(0,0,20), radius=25)
>>> [f.index for f in f4]
[1, 9, 16, 19, 27]

findAt(...)

Sequences of vertices, edges, faces and cells have the method

  • <sequence>.findAt(coordinates)

For instance, selecting both the bottom face and the top face:

>>> f5 = prt.faces.findAt(coordinates=((50,25,0),(50,25,20)))
>>> prt.Set(name='faces top bot', faces=f5)

or cells corresponding to layer 1, 3 and 5:

>>> c1 = prt.cells.findAt(coordinates=((50,25,1),(50,25,10),(50,25,19)))
>>> prt.Set(name='cells every 2nd', cells=c1)

getClosest(...)

Sequences of vertices, edges and faces (but not cells) have the method

  • <sequence>.getClosest(coordinates, searchTolerance)

where searchTolerance is optional (default to half of the maximum dimension of the part).

Unlike the previous methods, a sequecen is not returned but a dictionary:

>>> test = prt.faces.getClosest( coordinates=((10,10,2), (10,10,23)))
>>> print test
{0: (mdb.models['M1'].parts['P1'].faces[19], (17.6776695296637, 17.6776695296637, 2.0)), 
 1: (mdb.models['M1'].parts['P1'].faces[1], (17.6776695296637, 17.6776695296637, 20.0))}

Generating a sequence from the data in the dictionary:

>>> faces = prt.faces[0:0]
>>> for value in test.values():
...     i = value[0].index
...     faces = faces + prt.faces[i:i+1]
>>> prt.Set(name='faces hole top bot', faces=faces)

pointOn

All geometrical enteties have the property <entety>.pointOn. The corresponding sequence has the property pointsOn (plural, if you did not spot that...), which returns the list of points on the enteties in the sequence.

For example, faces at x = 0:

>>> f1 = prt.faces.getByBoundingBox(xMax=0)
>>> f1.pointsOn
(((0.0, 33.333333, 14.666667),), ((0.0, 33.333333, 10.666667),), ((0.0, 41.666667, 17.333333),), 
 ((0.0, 33.333333, 2.666667),), ((0.0, 33.333333, 6.666667),))
>>>

The faces at x = 0 can easilly be selecte using criteria for values of pointOn coordinates. For example, the above selection can be made by generating a list of faces based on the criteria x = 0 wich is converted to a proper sequence by the constructor FaceArray()

>>> from part import FaceArray
>>> f2 = FaceArray([f for f in prt.faces if f.pointOn[0][0] == 0.0])

Verifying that they have identical content:

>>> [f.index for f in f1], [f.index for f in f2]
([2, 11, 13, 21, 28], [2, 11, 13, 21, 28])

Recall the task of selecting only the circular edges at the hole. A simpler alternative procedure using criteria for the values of pointOn can be the following:

>>> from part import EdgeArray
>>> e1 = prt.edges.getByBoundingBox(xMax=25,yMax=25)
>>> e2 = EdgeArray([e for e in e1 if e.pointOn[0][0]!=0.0 and e.pointOn[0][1]!=0.0])
>>> prt.Set(name='edges hole circular', edges=e2)

Custom tool: getByPO(...)

The logic behind entity selection based on the property pointOn is very simple. However, it requires several lines of code. Therefore, a generic function for the task is suggested:

In [ ]:
def getByPO(seq, x=None, y=None, z=None):
    result = seq[0:0]
    for item in seq:
        xp, yp, zp = item.pointOn[0]
        xt = True if x==None else isapprox(x,xp)
        yt = True if y==None else isapprox(y,yp)
        zt = True if z==None else isapprox(z,zp)
        if xt and yt and zt:
            result = result + seq[item.index:item.index+1]
    return result

The argument seq is any sequence of geometrical entities (vertices, edges, faces or cells). The coordinate values are all optional since the default value is None.

Note that values are compared using the function isapprox() rather than the operator ==, see Geometrical tolerance

Examples of use:

    prt.Set(name='faces at x=0', faces=getByPO(prt.faces, x=0))
    prt.Set(name='faces at x=L', faces=getByPO(prt.faces, x=L))
    prt.Set(name='edges at x=L and y=b', edges=getByPO(prt.edges, x=L, y=b))
    e = getByPO(prt.edges, x=r, y=0) + getByPO(prt.edges, x=0, y=r)
    prt.Set('edges hole vertical', edges=e)

Selecting geometry

getSize(...)

The method getSize() applies to an edge, face or cell and returns length, area or volume. The method can be a versatile tool for making selections, but requires obviously some care with respect to the range of parameters; different sets of parameters may result in different selections.

Selecting geometry

Example: the length of the first edge in the sequence edges is:

>>> prt.edges[0].getSize( printResults=OFF)
50.0

Note the optional argument printResults=OFF: printing description and value is generally not useful in a script.

Generating a list of indices for the edges having length equal to the length L:

>>> [e.index for e in prt.edges if e.getSize(printResults=OFF)==L] 
[1, 12, 27, 31, 34, 50]

or all the edges having length equal to the layer thickness t/n:

>>> [e.index for e in prt.edges if e.getSize(printResults=OFF)==t/n] 
[5, 7, 8, 10, 11, 13, 15, 19, 21, 23, 24, 26, 28, 33, 35, 36, 38, 39, 43, 45, 46, 48, 49, 51, 54]

Thus, a way to create a set out of thees edges is:

>>> from part import EdgeArray
>>> edges = EdgeArray([e for e in prt.edges if e.getSize(printResults=OFF)==t/n]) 
>>> prt.Set(name='edges vertical', edges=edges)

Realize that alternative methods such as getByBoundingBox(...) would have required five lines of the operation compared to the single line use above.

Custom tool: getBySize(...)

The following function will work for sequences of edges, faces and cells:

In [ ]:
def getBySize(seq, size=None, smin=0, smax=1E9):
    result = seq[0:0]
    if size!=None:
        for item in seq:
            if isapprox(item.getSize(printResults=OFF), size):
                result = result + seq[item.index:item.index+1]
        return result
    else:
        for item in seq:
            s = item.getSize(printResults=OFF)
            if s>=smin and s<=smax:
                result = result + seq[item.index:item.index+1]
        return result

Examples of use:

The areas of all faces, rounded and sorted is

>>> sorted([round(f.getSize(printResults=OFF)) for f in prt.faces])
[100.0, 100.0, 100.0, 100.0, 100.0, 157.0, 157.0, 157.0, 157.0, 157.0, 200.0, 200.0, 200.0, 200.0, 200.0, 
 300.0, 300.0, 300.0, 300.0, 300.0, 400.0, 400.0, 400.0, 400.0, 400.0, 4509.0, 4509.0, 4509.0, 4509.0, 4509.0, 4509.0]

The function without the arguments size, smin and smax will return the same number of faces

>>> len(getBySize(prt.faces))
31

Faces with area equal to 200:

>>> len(getBySize(prt.faces, size=200))
5

Faces having areas greater than 500:

>>> len(getBySize(prt.faces, smin=500))
6

Creating a set of the faces at the hole

>>> r,tk = 25,4
>>> pi
>>> area=0.25*2*pi*r*tk
>>> print area
157.079632679
>>> prt.Set(name='faces hole', faces = getBySize(prt.faces, size=area))

getRadius()

A faces and edges have the method getRadius().

The methode returns the value of the radius if it exists, otherwise it raises an error and returns nothing:

>>> radius = prt.edges[0].getRadius()
Edge is not circular
>>> type(radius)
NameError: name 'radius' is not defined

That implies that simple list generation is not possible:

>>> [e.getRadius() for e in prt.edges]
Edge is not circular

The solution is to construct a try-except algorithm:

>>> for e in prt.edges:
...     try:
...         radius=e.getRadius()
...         print radius
...     except:
...         pass
25.0
25.0
25.0
25.0
25.0
25.0

Utilizing the technique in a custom tool:

Custom tool: getByR(...)

In [ ]:
def getByR(seq, r=None):
    result = seq[0:0]
    for item in seq:
        try:
            radius = item.getRadius()
            if r==None:
                result = result + seq[item.index:item.index+1]
            else:
                if isapprox(radius,r):
                    result = result + seq[item.index:item.index+1]
        except:
            pass
    return result

Examples of use:

Returning edges with a radius of any value:

>>> e = getByR(prt.edges)
>>> len(e)
6

Creating a set of the circular edges at the hole:

>>> prt.Set(name='edges circular', edges=getByR(prt.edges, r=25.0))

Selecting geometry

The Layered solid pipe is an example where this method can be very convenient: The task of creating a set of all cylindrical faces is now very simple:

>>> prt = mdb.models['M1'].parts['Pipe']
>>> set1=prt.Set(name='faces cylindrical', faces=getByR(prt.faces))

Visualizing only those faces:

>>> from caeModules import dgm
>>> leaf = dgm.LeafFromSets(sets=(set1, ))
>>> session.viewports['Viewport: 1'].partDisplay.displayGroup.replace(leaf=leaf)

Other methods

Several methods associates an entity to other enteties and vice versa, for instance

  • vertex.getEdges()
  • edge.getVertices()
  • edge.getAdjacentEdges()
  • edge.getFaces()
  • ...

Examples of use:

Selecting geometry

Getting the face on the top of the part:

>>> prt = mdb.models['M1'].parts['P1']
>>> t=20.0
>>> [f.index for f in prt.faces if f.pointOn[0][2]==t]
[29]

The edges associated with this face:

>>> edges = prt.faces[29].getEdges()
>>> print edges
(6, 14, 20, 27, 32)

The method returns a sequence of indices rather than a sequence of edges needed for a set:

>>> from part import EdgeArray
>>> e1 = EdgeArray([prt.edges[i] for i in edges])
>>> prt.Set(name='edges top', edges=e1)

Adjacent faces to the top faces, however, returns a seqence of faces:

>>> f1 = prt.faces[29].getAdjacentFaces()
>>> print f1
['Face object', 'Face object', 'Face object', 'Face object', 'Face object']

A set of the top face and the adjacent faces can now be created by

>>> prt.Set(name='faces top and adj', faces = prt.faces[29:30]+f1)

Finally, getFacesByFaceAngle(0) from the bottom cylindrical face is used to select all the cylindrical faces:

>>> f = prt.faces.getClosest(coordinates=((r*0.707,r*0.707,0.5*t/n),))[0][0]
>>> f1 = f.getFacesByFaceAngle(0)
>>> prt.Set(name='faces hole', faces=f1)

Boolean operations on sets

Selecting geometry

Example using operation=DIFFERENCE:

>>> e1 = prt.edges.getByBoundingBox(xMax=r,yMax=r)
>>> s1 = prt.Set(name='edges hole', edges=e1)
>>> e2 = prt.edges.getByBoundingBox(xMax=0,yMax=r)
>>> e3 = prt.edges.getByBoundingBox(xMax=r,yMax=0)
>>> s2 = prt.Set(name='edges hole vertical', edges=e2+e3)
>>> s3 = prt.SetByBoolean(name='edges hole circular', sets=(s1, s2), 
                          operation=DIFFERENCE)

Example using operation=UNION:

>>> f1 = prt.faces.getByBoundingBox(xMax=0)
>>> s4 = prt.Set(name='faces at x=0', faces=f1)
>>> f2 = prt.faces.getByBoundingBox(yMax=0)
>>> s5 = prt.Set(name='faces at y=0', faces=f2)
>>> s6 = prt.SetByBoolean(name='faces at x=0 and y=0', sets=(s4, s5), 
                          operation=UNION)
TOC Next Prev

Disclaimer:This site is designed for educational purposes only. There are most likely errors, mistakes, typos, and poorly crafted statements that are not detected yet... www.ntnu.edu/employees/nils.p.vedvik

Copyright 2024, All rights reserved