# -*- coding: utf-8 -*-
#
# This file is subject to the terms and conditions defined in
# file 'LICENSE.txt', which is part of this source code package.
#
"""Inp file reader (Abaqus simulation file)
"""
import os
import re
import csv
import numpy as np
from Muscat.Types import MuscatFloat, MuscatIndex
from Muscat.Helpers.Timer import Timer
import Muscat.Containers.ElementsDescription as ED
from Muscat.Containers.Filters.FilterObjects import ElementFilter
from Muscat.IO.ReaderBase import ReaderBase
from Muscat.IO.AbaqusTools import InpNameToMuscat, permutation
import Muscat.FE.ProblemData as ProblemData
from Muscat.LinAlg.Transform import Transform
import Muscat.Containers.Mesh as UM
KeywordToIgnore = ["INITIAL CONDITIONS",
"AMPLITUDE",
"EXPANSION",
"DISTRIBUTION TABLE",
"COUPLING",
"SOLID SECTION",
"CONNECTOR SECTION",
"SURFACE",
"SURFACE INTERACTION",
"FRICTION",
"CONTACT PAIR",
"CLEARANCE",
"PARAMETER",
"PART",
"ED. PART",
"ASSEMBLY",
"INSTANCE",
"ED. INSTANCE",
"ED. ASSEMBLY",
"PREPRINT",
"Step",
"Static",
"SOLVER",
"Output",
"NODE OUTPUT",
"Element Output",
"LOAD CASE",
"Boundary",
"End Step",
"SOLVER CONTROLS",
]
intFilter = re.compile("^[0-9]*$")
[docs]def JoinInp(filename):
fII = open("join_"+filename,"w")
def copyContent(filename):
for l in open(filename,"r"):
if len(l) >=8 and l[0:8] == "*INCLUDE":
copyContent( l.split("=")[1].strip())
pass
else:
fII.write(l)
copyContent(filename)
[docs]def SplitInp(filename):
f = InpReader()
f.SetFileName(fileName= filename)
fII = open("split_"+filename,"w")
f.StartReading()
pairs = {"PART":"*ED. PART",
"INSTANCE":"*ED. INSTANCE",
"STEP":"*ED. STEP",
"Step":"*End Step",
"ASSEMBLY":"*ED. ASSEMBLY",}
def WriteOnFile(inputFile, outputFile, waitFor="*", pwd="./"):
print("working on " , " ", pwd)
if pwd != "./" and waitFor != "*":
os.mkdir(pwd)
keywordCpt = 0
l = inputFile.ReadCleanLine()
while(True):
if l is None:
return None
if l[0:len(waitFor)] == waitFor:
if waitFor == "*":
return l
else:
outputFile.write(l+"\n")
return inputFile.ReadCleanLine()
if l[0] == "*":
localData = LineToDic(l)
keyword = localData["KEYWORD"]+"_"+str(keywordCpt)
keywordCpt += 1
outputFile.write("*INCLUDE INPUT="+pwd+keyword+".partial\n")
kf = open(pwd+keyword+".partial","w")
kf.write(l+"\n")
if localData["KEYWORD"] in pairs:
waitForIn=pairs[localData["KEYWORD"]]
else:
waitForIn="*"
print("Creating file ", pwd+keyword+"/main.partial","w")
l = WriteOnFile(f, kf, waitFor=waitForIn, pwd=pwd+keyword+"/")
else:
outputFile.write(l+"\n")
l = inputFile.ReadCleanLine()
WriteOnFile(f,fII,waitFor="$$",pwd="./")
[docs]def LineToDic(text):
res = {}
for l in csv.reader([text], delimiter=',', quotechar='"'):
for f in l:
if len(f) == 0:
continue
if f[0] == "*":
res["KEYWORD"] = f[1:]
else:
if f.find("=") >-1:
s = f.split("=")
res[s[0].lstrip().rstrip().upper()] = s[1].lstrip().rstrip().lstrip('"').rstrip('"')
else:
res[f.lstrip().rstrip().upper()] = True
return res
[docs]def LineToList(text):
return list(csv.reader([text], delimiter=',', quotechar='"'))[0]
[docs]def LineToListNoQuote(text):
return [s.strip() for s in text.split(",")]
[docs]def DiscardTillNextStar(func):
while(True):
currentText = func()
if currentText is None:
break
if len(currentText) > 1 and currentText[0] == "*":
break
return currentText
[docs]def ReadInp(fileName:str='',string:str='',out=None,**kwargs):
"""Function API for reading an Abaqus inp file
Parameters
----------
fileName : str, optional
name of the file to be read, by default None
string : str, optional
data to be read as a string instead of a file, by default None
out : Mesh, optional
output unstructured mesh object containing reading result, by default None
Returns
-------
Mesh
output unstructured mesh object containing reading result
"""
reader = InpReader()
reader.SetFileName(fileName)
reader.SetStringToRead(string)
return reader.Read(fileName=fileName, string=string,out=out,**kwargs)
[docs]class InpReader(ReaderBase):
"""Inp Reader class
"""
def __init__(self):
super().__init__()
self.commentHeader= "**"
self.readFormat = 'r'
self.meta = None
self.includeReaders = []
[docs] def find(self,l,expr):
res = l.upper().find(expr.upper())
return res
[docs] def PeekLine(self)-> str:
"""Read a line without advancing
Returns
-------
str
the next line in the input buffer
"""
if len(self.includeReaders) :
return self.includeReaders[-1].PeekLine()
return super().PeekLine()
[docs] def ReadCleanLine(self):
"""Read the next data line in the file (ignore comments)"""
# in the inp abaqus the lines ending in ',' are splitted in multiple lines
if len(self.includeReaders) :
res = self.includeReaders[-1].ReadCleanLine()
if res is None:
self.includeReaders.pop()
return self.ReadCleanLine()
else:
return res
res = super().ReadCleanLine()
if res is None:
return res
#here open the incuded file an put it in the lifo list
if res.startswith("*INCLUDE"):
localData = LineToDic(res[8:])
localFilename = localData["INPUT"]
localReader = InpReader()
if not os.path.isabs(localFilename):
localFilename = self.filePath + localFilename
localReader.SetFileName(localFilename)
localReader.StartReading()
self.includeReaders.append(localReader)
return self.ReadCleanLine()
if res[-1] == ",":
line = self.PeekLine()
if len(line) == 0:
return res
if line[0] != "*":
return res + " "+ super().ReadCleanLine()
return res
[docs] def Read(self,fileName=None,string=None, out=None):
"""Function that performs the reading of an Inp file
Parameters
----------
fileName : str, optional
name of the file to be read, by default None
string : str, optional
data to be read as a string instead of a file, by default None
out : Mesh, optional
output unstructured mesh object containing reading result, by default None
Returns
-------
Mesh
output unstructured mesh object containing reading result
"""
if fileName is not None:
self.SetFileName(fileName)
if string is not None:
self.SetStringToRead(string)
self.StartReading()
if out is None:
res = UM.Mesh()
else:
res = out
coefficient = 1.
meta = ProblemData.ProblemData()
fileToInternalIdPoint = {}
fileToInternalIdElement = {}
fileToGlobalElementId = {}
l = self.ReadCleanLine()
FENames = {}
while(True):
print(l)
if not l: break
localData = LineToDic(l)
if "KEYWORD" in localData and localData["KEYWORD"] in KeywordToIgnore:
print("Ignoring keyword: '" + str(localData["KEYWORD"]) +"' jumping to the next star" )
l = DiscardTillNextStar(self.ReadCleanLine )
continue
if self.find(l,"*HEADING")>-1:
l = self.ReadCleanLine()
HEADING = ""
while(True):
if l is None or l.find("*") > -1 or not l:
break
HEADING += str(l) + "\n"
l = self.ReadCleanLine()
continue
if self.find(l,"**LENGTH UNITS")>-1:
if l.find("mm")>-1:
coefficient = 0.001
l = self.ReadCleanLine()
continue
if self.find(l,"*NODE")>-1:
nodes= []
originalIds = []
cpt:MuscatIndex = 0
l = self.ReadCleanLine()
dim:MuscatIndex = 3
s = None
while(True):
if len(l) == 0 or l[0]=="*" or not l:
break
s = LineToListNoQuote(l)
oid = int(s[0])
fileToInternalIdPoint[oid] = cpt
nodes.append(list(map(float,s[1:])) )
originalIds.append(oid)
cpt += 1
l = self.ReadCleanLine()
if s is not None:
# we use the last point to detect the dimensionality of the mesh
dim = len(s)-1
res.nodes = np.array(nodes,dtype=MuscatFloat)
res.nodes.shape = (cpt,dim)
res.originalIDNodes = np.array(originalIds,dtype=MuscatIndex)
continue
if self.find(l,"*ELEMENT")>-1:
data = LineToDic(l)
elementType = data["TYPE"]
elementName = InpNameToMuscat[elementType]
per = permutation.get(elementType,None)
l = self.ReadCleanLine()
elements = res.GetElementsOfType(elementName)
initialNumberOfElements = elements.GetNumberOfElements()
while(True):
if l is None or not l or l[0]== "*" :
break
s = LineToListNoQuote(l)
oid = int(s[0])
conn = [fileToInternalIdPoint[x] for x in map(int,s[1:]) ]
cid = elements.AddNewElement(conn,oid)-1
if elementName not in FENames:
FENames[elementName] = []
FENames[elementName].append(elementType)
fileToInternalIdElement[oid] = (elements,cid)
l = self.ReadCleanLine()
if per is not None:
elements.connectivity = elements.connectivity[:,per]
finalNumberOfElements = elements.GetNumberOfElements()
if "ELSET" in data:
elementSetName = data["ELSET"]
elements.GetTag(elementSetName).AddToTag(range(initialNumberOfElements,finalNumberOfElements))
elif elementType == "CONN3D2":
elements.GetTag("CONN3D2").AddToTag(range(initialNumberOfElements,finalNumberOfElements))
res.ComputeGlobalOffset()
continue
if self.find(l,"*NSET")>-1:
data = LineToDic(l)
nodeSetName = data['NSET']
l = self.ReadCleanLine()
nodesIds = []
if "GENERATE" in localData and localData["GENERATE"]:
d = LineToList(l)
d = (list(map(int,d) ))
nodesIds = range(d[0],d[1]+1,d[2])
tag = res.nodesTags.CreateTag(nodeSetName,False)
tagsIds = [fileToInternalIdPoint[x] for x in nodesIds if x in fileToInternalIdPoint ]
if len(tagsIds) != len(nodesIds):
print("Warning NSET GENERATE : not all the node ids generated are present in the mesh ")
tag.AddToTag(tagsIds)
l = self.ReadCleanLine()
continue
else:
while(True):
if l is None:
break
if l.find("*") > -1 or not l:
break
s = l.replace(',', '').split()
nodesIds.extend(map(int,s))
l = self.ReadCleanLine()
continue
tag = res.nodesTags.CreateTag(nodeSetName,False)
tag.AddToTag([fileToInternalIdPoint[x] for x in nodesIds ])
continue
globalOffset = res.ComputeGlobalOffset()
if len(fileToGlobalElementId) == 0:
for (oi,(elements, id)) in fileToInternalIdElement.items():
fileToGlobalElementId[oi] = globalOffset[elements.elementType] + id
if self.find(l,"*ELSET")>-1:
elementSetName = localData['ELSET']
l = self.ReadCleanLine()
ds = []
tagsNames = []
while(True):
if l is None or l.find("*") > -1 or not l:
if len(ds) > 0:
ids = [fileToGlobalElementId[dd] for dd in ds ]
res.AddElementsToTag(ids, elementSetName )
if len(tagsNames) >0 :
for elName, elData, elIds in ElementFilter(res, eTag=tagsNames):
tag = elData.tags.CreateTag(elementSetName,False).AddToTag(elIds)
break
s = LineToListNoQuote(l)
# number are ids, str are names
ds.extend([int(ss) for ss in s if intFilter.match(ss) ] )
tagsNames.extend([ss for ss in s if not intFilter.match(ss) ] )
l = self.ReadCleanLine()
continue
continue
if self.find(l,"*DISTRIBUTION")>-1:
data = LineToDic(l)
location = data['LOCATION'] # "ELEMENT"
name = data['NAME'] # "ELEMENT"
table = data['TABLE'] # "ELEMENT"
if table == "DistributionTable_Orientation":
NumberOfData = 6
elif table == "DistributionTable_Density":
NumberOfData = 1
elif table == "DistributionTable_Elastic":
NumberOfData = 9
elif table == "DISTRIB_TABLE":
NumberOfData = 9
else:
raise Exception("Error! ")
data = np.zeros((res.GetNumberOfElements(),NumberOfData))
buffer = np.zeros(NumberOfData)
if location == "ELEMENT":
l = self.ReadCleanLine()
s = l.split(',')
if len(s[0]) == 0:
#default values
s = list(map(float,s[1:]))
if len(s) < NumberOfData:
# multiline data
s.extend(map(float,self.ReadCleanLine().split(',')) )
s = np.array(s)
for i,v in enumerate(s):
data[:,i] = v
l = self.ReadCleanLine()
while(True):
if l is None or l.find("*") > -1 or not l:
break
s = l.split(",")
elementTagName = s[0].split(".")[-1]
buffer[0:len(s)-1] = np.array(s[1:], dtype = MuscatFloat )
if len(s) < NumberOfData:
# multiline data
buffer[len(s)-1:] = np.fromstring(self.ReadCleanLine(), dtype =MuscatFloat, sep="," )
#s.extend( )
#map(float,self.ReadCleanLine().replace(',', ' ').split()) )
#else :
# s = np.array(s[1:], dtype = MuscatFloat ) list(map(float,s[1:]))
#s= np.array(s)
for elementName, elementData, elementsIds in ElementFilter(res ,tag=elementTagName):
data[elementsIds+elementData.globaloffset,:] = buffer
l = self.ReadCleanLine()
if table == "DistributionTable_Orientation":
res.elemFields["V1"] = data[:,0:3]
res.elemFields["V2"] = data[:,3:]
elif table == "DistributionTable_Density":
res.elemFields["density"] = data
elif table == "DistributionTable_Elastic":
res.elemFields["E"] = data
res.elemFields["E1"] = data[:,0]
res.elemFields["E2"] = data[:,1]
res.elemFields["E3"] = data[:,2]
res.elemFields["Nu12"] = data[:,3]
res.elemFields["Nu13"] = data[:,4]
res.elemFields["Nu23"] = data[:,5]
res.elemFields["G12"] = data[:,6]
res.elemFields["G13"] = data[:,7]
res.elemFields["G23"] = data[:,8]
continue
if self.find(l,"*MATERIAL") > -1:
data = LineToDic(l)
name = data["NAME"]
mat = ProblemData.Material()
while(True):
l = self.ReadCleanLine()
if l is None:
break
data = LineToDic(l)
t = data["KEYWORD"]
if t not in ["ELASTIC","DENSITY","EXPANSION","ELASTIC","DISTRIBUTION"] :
break
if t == "DISTRIBUTION":
print("Ignoring DISTRIBUTION")
l = DiscardTillNextStar(self.ReadCleanLine )
break
if t == "EXPANSION":
if "ZERO" in data:
mat.AddProperty(t,"ZERO",data["ZERO"])
if "TYPE" in data:
st = data["TYPE"]
else:
st = None
l = self.ReadCleanLine()
s = list(l.strip('\n').strip().split() )
mat.AddProperty(t,st,s)
meta.materials[name] = mat
continue
if self.find(l,"*ORIENTATION")>-1:
data = LineToDic(l)
orient = Transform()
name = data["NAME"]
orient.system = data["SYSTEM"]
if orient.system != "RECTANGULAR":
s = list(map(float, self.ReadCleanLine().replace(","," ").split() ))
orient.SetFirst(s[0:3])
orient.SetSecond(s[3:6])
if len(s) >= 9:
orient.SetOffset(s[6:9])
meta.orientations[name] = orient
l = DiscardTillNextStar(self.ReadCleanLine )
continue
if self.find(l,"*SURFACE")>-1:
data = LineToDic(l)
name = data["NAME"]
if data["TYPE"] == "ELEMENT":
l = self.ReadCleanLine()
while(True):
if l is None:
break
if l.find("*") > -1 or not l:
break
s = l.split(",")
originalElemNumber = int(s[0])
faceNumber = int(s[1].lstrip().rstrip()[-1])-1
elements,cid = fileToInternalIdElement[originalElemNumber][0]
connectivity = elements.connectivity[cid,:]
faceType, faceLocalConnectivity = ED.faces[elements.elementType][faceNumber]
faceConnectivity = connectivity[faceLocalConnectivity]
elements = res.GetElementsOfType(faceType)
cid = elements.AddNewElement(faceConnectivity,-1)
if faceType not in FENames:
FENames[faceType] = []
FENames[faceType].append("NA")
elements.GetTag(name).AddToTag(cid-1)
l = self.ReadCleanLine()
continue
res.ComputeGlobalOffset()
continue
else:
raise Exception("NOT IMPLEMENTED sorry")
#*COUPLING, CONSTRAINT NAME="Coupling-1", REF NODE=239100, SURFACE="Rigid Connection1-1"
#*KINEMATIC
#1, 6
if localData["KEYWORD"] == "STEP":
data = LineToDic(l)
name = data["NAME"]
l = self.ReadCleanLine()
cs = ProblemData.StudyCase()
while(True):
data = LineToDic(l)
if "KEYWORD" in data and data["KEYWORD"] in [ "ED. STEP", "END STEP"]:
l = self.ReadCleanLine()
break
if "KEYWORD" in data and data["KEYWORD"] == "STATIC":
cs.type = "STATIC"
l = DiscardTillNextStar(self.ReadCleanLine)
continue
print(l)
print(localData)
print(("line starting with <<"+l[:20]+">> not considered in the reader"))
l = self.ReadCleanLine()
raise Exception("Error reading file")
self.EndReading()
res.originalIDNodes = np.squeeze(res.originalIDNodes)
feNames = []
for elementName in res.elements.keys():
feNames.extend(FENames[elementName])
res.elemFields["FE Names"] = np.array(feNames,dtype=np.str_)
res.PrepareForOutput()
self.meta = meta
return res
from Muscat.IO.IOFactory import RegisterReaderClass
RegisterReaderClass(".inp",InpReader)
[docs]def CheckIntegrity():
res1 = LineToDic('*NSET, NSET="Fixed Displacement1", KEY2=5')
if res1['KEY2'] != '5':
return "not ok"
data = u"""** -------------------------------------------------------
** ABAQUS input file
** File exported by VISUAL-ED.IRONMENT : Version10.7
** on 2016-4-8, at 10Hr:44min
** -------------------------------------------------------
**LENGTH UNITS: mm
*NODE
1, 3.0310898125000696, 1.7500003247594429, 0.00059999999999149622
2, 2.9785080000000002, 0.87500000000000011, 0.75012199999999996
3, 3.1961719999999998, 1.0006690000000003, 1.5926899999999999
4, 2.2943020000000001, 0.4799735, 1.4870170000000003
5, 2.9259249999999999, 0., 1.4996439999999893
6, 2.7781790000000002, 0.78753359999999994, 2.3200409999999998
*ELEMENT, TYPE=C3D4, ELSET=AM1_labo
1, 1, 2, 3, 4
2, 3, 5, 6, 4"""
res = ReadInp(string=data)
from Muscat.Helpers.IO.TemporaryDirectory import TemporaryDirectory
tempdir = TemporaryDirectory.GetTempPath()
f =open(tempdir+"test.inp","w")
f.write(data)
f.close()
res = ReadInp(fileName=tempdir+"test.inp")
print(res)
return 'ok'
if __name__ == '__main__':
print(CheckIntegrity())# pragma: no cover