Reputation: 315
Does anyone of you know of (if there exists) a way to extract node numbers of an external surface of a model in Abaqus? By a surface I dont mean an entity, Im talking purely about an outside area of an object.
Thanks!
Upvotes: 0
Views: 2203
Reputation: 2357
If you have defined a Set or Surface, getting the nodes is trivial:
p = mdb.models[name].parts[name]
# Get the Node objects on the previously defined surface:
node_objects = p.surfaces[name].nodes
# Same from a set:
node_objects = p.sets[name].nodes
# Get the labels for the Node objects:
node_labels = [node.label for node in node_objects]
If you define the Set or Surface using the part geometry, it doesn't change if you remesh the part.
However, if you do not have a Set or Surface, and you can't create/get one easily, then you have to loop over some other object in the part that you can use to check if it's on the surface. One approach is shown by @max9111. However, I suggest looping over the part elementFaces
list. This is a list of unique Face objects defined by the elements of the mesh. I say unique because if two elements share a face, it's only put in the list once. This is different from the very similarly named elemFaces
list. Look it up.
In the example below, you get the Node objects directly, and from them you can get the node labels/coordinates/etc if desired.
p = mdb.models[name].parts[name]
surf_nodes = []
for face in p.elementFaces():
if len(face.getElements()) == 1:
# Then the face has only one associated element, ie it's on the surface.
# Get the nodes on the face:
surf_nodes.extend([node for node in face.getNodes() if node not in surf_nodes])
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Example usage/output for some arbitrary part/mesh:
>>>len(surf_nodes) # <-- A normal list of node objects.
14
>>>surf_nodes[0] # <-- Refer to an individual node object.
mdb.models[name].parts[name].nodes[2]
>>>surf_nodes[0].label # <-- From it you can access all kinds of stuff.
3
>>>surf_nodes[0].coordinates
(0.0, 10.0, 10.0)
And so, in 5 lines of code you pretty efficiently obtain all of the nodes over the entire surface of the mesh. This works for any element type in the mesh, of course. Unfortunately, you still loop over all internal faces, but that's fewer operations than checking the face on each element, since each internal face must only be checked once. That said, you could probably reduce the number of faces that must be checked, but that is for another question.
Upvotes: 4
Reputation: 6492
At first you will need the Connectivity of your Elements and the Element Type. In the Abaqus manual(+) you will find the definition of the element faces. Each face which exists only once in your model is a surface face, so the nodes belonging to that surface faces are surface nodes.
(+) 28.1.4 in the Abaqus Analysis User's Guide
The following example needs numpy >=1.9. If you have an older numpy version you have to find another way to get faces which occur only once.
# for example C3D4, np_Connectivity is a numpy array describing the element connectivity
def get_Surface_Nodes_tet(np_Connectivity):
#Face definition
Face=np.concatenate((np_Connectivity[:,[0,1,2]],np_Connectivity[:,[0,3,1]],np_Connectivity[:,[1,3,2]],np_Connectivity[:,[2,3,0]]))
#Sort the nodes of the faces
Face.sort()
#get the faces which are only once in the array
b = np.ascontiguousarray(Face).view(np.dtype((np.void, Face.dtype.itemsize * Face.shape[1])))
#min numpy version=1.9
_, idx_2,counts = np.unique(b, return_index=True,return_counts=True)
only_once=np.where(counts<2)
idx=idx_2[only_once[0]]
#All nodes of faces, which occur only once are surface nodes
SurfaceNodeLabels=np.unique(Face[idx])
return SurfaceNodeLabels
EDIT The following function shows how to get the surface Nodes with abaqus cae. So for this version a license of abaqus cae is required.
def get_Surface_Nodes(Faces):
surface_Faces=[]
#get the surface Faces
for i in xrange(0,len(Faces)):
Elements=Faces[i].getElements()
if Elements is not None:
if len(Elements)==1:
surface_Faces.append(i)
S_Node_Labels=[]
#get the corresponding node labels
for i in surface_Faces:
NodeO=Faces[i].getNodes()
for Node in NodeO:
S_Node_Labels.append(Node.label)
S_Node_Labels=np.unique(S_Node_Labels)
return S_Node_Labels
And a example how to use this function:
import part
import assembly
import numpy as np
#Get the Element Faces
Faces=mdb.models['Model_1'].rootAssembly.instances['Instance_1'].elementFaces
SurfaceNodeLabels=get_Surface_Nodes(Faces)
Upvotes: 1