Skip to content

Instantly share code, notes, and snippets.

@anderson2981
Created May 1, 2024 18:53
Show Gist options
  • Save anderson2981/1fb6d9d7d79002e3b3430af9c55c3a20 to your computer and use it in GitHub Desktop.
Save anderson2981/1fb6d9d7d79002e3b3430af9c55c3a20 to your computer and use it in GitHub Desktop.
def read_nastran_mesh(file_path):
nodes = {}
elements = {}
element_tags = {}
physical_names = {}
physical_names_dim = {}
with open(file_path, "r") as file:
lines = file.readlines()
# Flag variables to determine whether to read nodes or elements
reading_nodes = False
reading_elements = False
reading_physical_names = False
num_nodes = 0
num_elements = 0
num_physical_names = 0
physical_name = ""
records = []
current_record = ""
# first check for continuation lines, these need to be combined
for line in lines:
line = line.rstrip('\n')
if line.startswith('+'):
# Lines that start with plus belong to the previous line,
# remove the + and concatenate
current_record = current_record.rstrip('+')
# remove the first 8 character record, this includes the +
current_record += line[8:]
else:
if current_record:
records.append(current_record)
current_record = line
if current_record:
records.append(current_record)
# operate on the concatenated file
for line in records:
if line.startswith("$ Node cards"):
reading_nodes = True
reading_elements = False
reading_physical_names = False
continue
elif line.startswith("$ Element cards"):
reading_elements = True
reading_nodes = False
reading_physical_names = False
continue
elif line.startswith("$ Property cards"):
reading_elements = False
reading_nodes = False
reading_physical_names = True
continue
elif line.startswith("$ Material cards"):
reading_elements = False
reading_nodes = False
reading_physical_names = False
continue
def read_line(line, field_length=8):
fields = [line[i:i+field_length] for i in range(0,len(line), field_length)]
return fields
if reading_nodes:
if line.startswith("GRID"):
parts = read_line(line)
num_fields = len(line)/8
node_id = int(parts[1])
scale = 1.
scale = 0.001
x = float(parts[3])*scale
y = float(parts[4])*scale
z = float(parts[5])*scale if len(parts) > 5 else 0.0
nodes[node_id] = (x, y, z)
elif reading_elements:
if line.startswith("CQUAD") or\
line.startswith("CHEX") or\
line.startswith("CROD"):
parts = read_line(line)
element_id = int(parts[1])
element_nodes = [int(parts[i]) for i in range(3, len(parts))]
elements[element_id] = element_nodes
if element_id in element_tags:
element_tags[element_id].append(int(parts[2]))
else:
element_tags[element_id] = [int(parts[2])]
elif reading_physical_names:
if line.startswith("$ Name:"):
num_physical_names += 1
parts = line.split()
physical_name = parts[2]
#physical_names[num_physical_names] = physical_name
if line.startswith("PROD"):
pdim = 1
#parts = line.split()
parts = read_line(line)
physical_id = int(parts[1])
physical_names_dim[physical_id] = pdim
physical_names[physical_id] = physical_name
elif line.startswith("PSHELL"):
pdim = 2
#parts = line.split()
parts = read_line(line)
physical_id = int(parts[1])
physical_names_dim[physical_id] = pdim
physical_names[physical_id] = physical_name
elif line.startswith("PSOLID"):
pdim = 3
#parts = line.split()
parts = read_line(line)
physical_id = int(parts[1])
physical_names_dim[physical_id] = pdim
physical_names[physical_id] = physical_name
# sort the nodes
sorted_nodes = dict(sorted(nodes.items()))
sorted_elements = dict(sorted(elements.items()))
return sorted_nodes, sorted_elements, element_tags, physical_names, physical_names_dim
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment