You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
268 lines
10 KiB
Python
268 lines
10 KiB
Python
2 years ago
|
# import necessary modules to handle Abaqus output database, files and string
|
||
|
from odbAccess import *
|
||
|
from textRepr import *
|
||
|
from string import *
|
||
|
|
||
|
import os
|
||
|
import time
|
||
|
|
||
|
|
||
|
def ConvertOdb2Vtk(): # Modify the default value of filename here to specify the default configuration file
|
||
|
starttime = time.time()
|
||
|
|
||
|
# display the reading result of odb2vtk file
|
||
|
print("odb2vtk reading finished, time elapsed: "), time.time()-starttime
|
||
|
print("Basic Information:")
|
||
|
print("Model:", odb_path, "; Mesh type:",
|
||
|
mesh_name, "; Number of blocks:", 1)
|
||
|
print("Convert frames: ", input_frame[0], " to ", input_frame[-1])
|
||
|
print("Step & Instance : ", str(input_step), ", ", str(input_instance))
|
||
|
|
||
|
# open an ODB ( Abaqus output database )
|
||
|
odb = openOdb(os.path.join(odb_path), readOnly=True)
|
||
|
print("ODB opened")
|
||
|
|
||
|
# access geometry and topology information ( odb->rootAssembly->instances->(nodes, elements) )
|
||
|
rootassembly = odb.rootAssembly
|
||
|
instance = rootassembly.instances
|
||
|
# access attribute information
|
||
|
step = odb.steps
|
||
|
# get instance & step information : Quantity and all names
|
||
|
allinstancestr = str(instance)
|
||
|
autoins = allinstancestr.split("'")
|
||
|
inslen = len(autoins)/4
|
||
|
instance_N = range(0, inslen)
|
||
|
allstepstr = str(step)
|
||
|
autostep = allstepstr.split("'")
|
||
|
steplen = len(autostep)/4
|
||
|
step_N = range(0, steplen)
|
||
|
|
||
|
for i in input_step:
|
||
|
if (steplen < int(i)):
|
||
|
print("input step exceeds the range of steps")
|
||
|
os._exit(0)
|
||
|
for i in input_instance:
|
||
|
if (inslen < int(i)):
|
||
|
print("input instance exceeds the range of instances")
|
||
|
os._exit(0)
|
||
|
|
||
|
# step cycle
|
||
|
for step_i in input_step:
|
||
|
n = int(step_i)*4+1
|
||
|
stepname = autostep[n]
|
||
|
print("Step: ", stepname)
|
||
|
# instance cycle
|
||
|
for ins_i in input_instance:
|
||
|
n = int(ins_i)*4+1
|
||
|
instancename = autoins[n]
|
||
|
print("Instance: ", instancename)
|
||
|
|
||
|
# access nodes & elements
|
||
|
node = instance[instancename].nodes
|
||
|
element = instance[instancename].elements
|
||
|
n_nodes = len(node)
|
||
|
n_elements = len(element)
|
||
|
# access attribute(fieldOutputs) information
|
||
|
frame = step[stepname].frames
|
||
|
print('all frame',frame)
|
||
|
|
||
|
# compute the number of element of each block
|
||
|
p_elements = n_elements/1 + 1
|
||
|
lp_elements = n_elements - (p_elements*(1-1)) # last block
|
||
|
|
||
|
# match nodes' label and its order in sequence (for empty nodes in tetra mesh)
|
||
|
MLN = node[n_nodes-1].label
|
||
|
TOTAL = []
|
||
|
# read node in sequence, and get the largest label of node(non-empty)
|
||
|
# MLN is the max label of nodeset
|
||
|
for i in node:
|
||
|
TOTAL.append(i.label)
|
||
|
if (i.label > MLN):
|
||
|
MLN = i.label
|
||
|
# match (the key)
|
||
|
L = []
|
||
|
n = 0
|
||
|
for i in range(MLN):
|
||
|
L.append(0)
|
||
|
for i in TOTAL:
|
||
|
L[i-1] = n
|
||
|
n += 1
|
||
|
|
||
|
# frame cycle
|
||
|
for i_frame in input_frame:
|
||
|
|
||
|
# Detect whether the input frame is out of range
|
||
|
try:
|
||
|
odb.steps[stepname].frames[int(i_frame)]
|
||
|
except:
|
||
|
print("input frame exceeds the range of frames")
|
||
|
os._exit(0)
|
||
|
break
|
||
|
|
||
|
# Access a frame
|
||
|
N_Frame = odb.steps[stepname].frames[int(i_frame)]
|
||
|
print("Frame:", i_frame)
|
||
|
|
||
|
print("Partitionning model and writing vtk files ......")
|
||
|
# piece cycle, to partion the model and create each piece for vtk files
|
||
|
|
||
|
time1 = time.time()
|
||
|
print("frame:", i_frame, ";")
|
||
|
# Reorganization
|
||
|
# Control&Storage
|
||
|
# estimate whether the node has already existed
|
||
|
stg_p = []
|
||
|
# store the reorganized node for element
|
||
|
stg_e = []
|
||
|
# store the reorganized node for node
|
||
|
stg_n = []
|
||
|
for i in range(MLN):
|
||
|
stg_p.append(-1)
|
||
|
nodecount = 0
|
||
|
# reorganize the node and element (reconstruct the mesh)
|
||
|
|
||
|
M = range(0, n_elements)
|
||
|
for i in M:
|
||
|
for j in range(mesh_conner):
|
||
|
k = element[i].connectivity[j] - 1
|
||
|
if (stg_p[k] < 0):
|
||
|
stg_p[k] = nodecount
|
||
|
stg_n.append(L[k])
|
||
|
stg_e.append(nodecount)
|
||
|
nodecount += 1
|
||
|
else:
|
||
|
stg_e.append(stg_p[k])
|
||
|
# compute point quantity
|
||
|
n_reop = len(stg_n)
|
||
|
reop_N = range(0, len(stg_n))
|
||
|
|
||
|
# create and open a VTK(.vtu) files
|
||
|
|
||
|
outfile = open(os.path.join(vtk_path)+'_'+stepname +
|
||
|
'_'+instancename+'f%03d' % int(i_frame)+'.vtu', 'w')
|
||
|
|
||
|
# <VTKFile>, including the type of mesh, version, and byte_order
|
||
|
outfile.write(
|
||
|
'<VTKFile type="UnstructuredGrid" version="0.1" byte_order="LittleEndian">'+'\n')
|
||
|
# <UnstructuredGrid>
|
||
|
outfile.write('<UnstructuredGrid>'+'\n')
|
||
|
# <Piece>, including the number of points and cells
|
||
|
outfile.write('<Piece NumberOfPoints="'+str(n_reop) +
|
||
|
'"'+' '+'NumberOfCells="'+str(lp_elements)+'">'+'\n')
|
||
|
|
||
|
print("Writing Nodes ......")
|
||
|
# <Points> Write nodes into vtk files
|
||
|
outfile.write('<Points>'+'\n')
|
||
|
outfile.write(
|
||
|
'<DataArray type="Float64" NumberOfComponents="3" format="ascii">'+'\n')
|
||
|
for i in reop_N:
|
||
|
nt = stg_n[i]
|
||
|
k = node[stg_n[i]].label-1
|
||
|
# base shape
|
||
|
X, Y, Z = node[nt].coordinates[0], node[nt].coordinates[1], node[nt].coordinates[2]
|
||
|
# modify shape
|
||
|
# X,Y,Z = node[nt].coordinates[0]+ux,node[nt].coordinates[1]+uy,node[nt].coordinates[2]+uz
|
||
|
outfile.write(' '+'%11.8e' % X+' '+'%11.8e' %
|
||
|
Y+' '+'%11.8e' % Z+'\n')
|
||
|
outfile.write('</DataArray>'+'\n')
|
||
|
outfile.write('</Points>'+'\n')
|
||
|
# </Points>
|
||
|
|
||
|
print("Writing Results data ......")
|
||
|
# <PointData> Write results data into vtk files
|
||
|
col = {"Scalars": [], "Vevtors": [], "Tensors": []}
|
||
|
# 'U','A', 'V', 'RF','PEEQ','S'
|
||
|
for var_id in ['NT11']:
|
||
|
try:
|
||
|
col["Scalars"].append("Temperature")
|
||
|
except:
|
||
|
print('jump', var_id)
|
||
|
con = "Scalars="+'"'+','.join(col["Scalars"])+'"'
|
||
|
# con = "Tensors="+'"'+','.join(col["Tensors"])+'"' + " "+ \
|
||
|
# "Vevtors="+'"'+','.join(col["Vevtors"])+'"' + " "+ \
|
||
|
# "Scalars="+'"'+','.join(col["Scalars"])+'"'
|
||
|
outfile.write("<"+"PointData"+" "+con+">"+'\n')
|
||
|
|
||
|
for var_id in ['NT11']:
|
||
|
fieldOutputs = N_Frame.fieldOutputs[var_id]
|
||
|
from utils_odb import NT11 as pq_class
|
||
|
pq_class(fieldOutputs,outfile,reop_N)
|
||
|
|
||
|
outfile.write("</PointData>"+'\n')
|
||
|
# </PointData>
|
||
|
|
||
|
print("Writing Cells ......")
|
||
|
# <Cells> Write cells into vtk files
|
||
|
outfile.write('<Cells>'+'\n')
|
||
|
|
||
|
# Connectivity 8 node
|
||
|
outfile.write(
|
||
|
'<DataArray type="Int32" Name="connectivity" format="ascii">'+'\n')
|
||
|
if (mesh_type == 12):
|
||
|
for i in range(len(stg_e)/8):
|
||
|
outfile.write(str(stg_e[i*8])+' '+str(stg_e[i*8+1])+' '+str(stg_e[i*8+2])+' '+str(stg_e[i*8+3])+' '+str(
|
||
|
stg_e[i*8+4])+' '+str(stg_e[i*8+5])+' '+str(stg_e[i*8+6])+' '+str(stg_e[i*8+7])+'\n')
|
||
|
if (mesh_type == 10):
|
||
|
for i in range(len(stg_e)/4):
|
||
|
outfile.write(str(
|
||
|
stg_e[i*4])+' '+str(stg_e[i*4+1])+' '+str(stg_e[i*4+2])+' '+str(stg_e[i*4+3])+'\n')
|
||
|
outfile.write('</DataArray>'+'\n')
|
||
|
|
||
|
# Offsets
|
||
|
outfile.write(
|
||
|
'<DataArray type="Int32" Name="offsets" format="ascii">'+'\n')
|
||
|
for i in range(len(stg_e)/mesh_conner):
|
||
|
outfile.write(str(i*mesh_conner+mesh_conner)+'\n')
|
||
|
outfile.write('</DataArray>'+'\n')
|
||
|
|
||
|
# Mesh Type
|
||
|
outfile.write(
|
||
|
'<DataArray type="UInt8" Name="types" format="ascii">'+'\n')
|
||
|
for i in range(len(stg_e)/mesh_conner):
|
||
|
outfile.write(str(mesh_type)+'\n')
|
||
|
outfile.write('</DataArray>'+'\n')
|
||
|
outfile.write('</Cells>'+'\n')
|
||
|
# </Cells>
|
||
|
|
||
|
# </Piece>
|
||
|
outfile.write('</Piece>'+'\n')
|
||
|
# </UnstructuredGrid>
|
||
|
outfile.write('</UnstructuredGrid>'+'\n')
|
||
|
# </VTKFile>
|
||
|
outfile.write('</VTKFile>'+'\n')
|
||
|
|
||
|
outfile.close()
|
||
|
print("Time elapsed: ", time.time() - time1, "s")
|
||
|
|
||
|
odb.close()
|
||
|
|
||
|
print("Total time elapsed: ", time.time() - starttime, "s")
|
||
|
|
||
|
|
||
|
# get odb file's path
|
||
|
odb_path = 'C:/Users/OPTX/Downloads/Digital-Twin/odb2vtk/Thermal.odb'
|
||
|
# get the output files' path
|
||
|
vtk_path = 'C:/Users/OPTX/Downloads/Digital-Twin/odb2vtk/' # not.vtu,.vtk
|
||
|
|
||
|
# get the mesh type
|
||
|
mesh_type = 12 # c3d8?
|
||
|
mesh_conner = 0
|
||
|
if (mesh_type == 12):
|
||
|
mesh_conner = 8
|
||
|
mesh_name = "Hexahedron"
|
||
|
if (mesh_type == 10):
|
||
|
mesh_conner = 4
|
||
|
mesh_name = "Tetra"
|
||
|
if (mesh_conner == 0):
|
||
|
print("Mesh type error or unidentified")
|
||
|
os._exit(0)
|
||
|
|
||
|
# get the frame
|
||
|
input_frame = range(1, 4+1)
|
||
|
# get the step
|
||
|
input_step = '0'.split(",")
|
||
|
# get the instance
|
||
|
input_instance = '0'.split(",")
|
||
|
# end reding and close odb2vtk file
|
||
|
ConvertOdb2Vtk()
|