Source code for Muscat.IO.LSDynaReader
# -*- 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.
#
""" LSDyna file reader.
Documentation of the format:
http://ftp.lstc.com/anonymous/outgoing/jday/manuals/DRAFT_Vol_I.pdf
"""
from Muscat.IO.IOFactory import RegisterReaderClass
import numpy as np
from Muscat.Types import MuscatIndex, MuscatFloat
import Muscat.MeshContainers.ElementsDescription as ED
from Muscat.MeshContainers.Mesh import Mesh
from Muscat.IO.ReaderBase import ReaderBase
from Muscat.Helpers.Logger import Debug, Info
LSDynaNumber = {4: ED.Tetrahedron_4} # 4-point tetraedron
[docs]
def ReadLSDyna(fileName: str = "", string: str = "", out=None, printNotRead=True):
"""Function API for reading a LSDyna mesh 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
printNotRead : bool, optional
if True, prints in console the lines dot understood by the reader, by default True
Returns
-------
Mesh
output unstructured mesh object containing reading result
"""
reader = LSDynaReader()
reader.SetFileName(fileName)
reader.SetStringToRead(string)
return reader.Read(fileName=fileName, string=string, out=out, printNotRead=printNotRead)
[docs]
def LineToListNoQuote(text):
return [s.strip() for s in text.split()]
[docs]
def ListToNumber(list):
"""hack where the element type is defined by inspecting the number of identical
columns at the end of the connectivity list.
"""
l = len(list)
val = list[-1]
for i in range(l - 2, -1, -1):
if list[i] != val:
break
return i + 2
[docs]
class LSDynaReader(ReaderBase):
"""LSDyna Reader class"""
def __init__(self):
super().__init__()
self.commentHeader = "$"
self.readFormat = "r"
[docs]
def Read(self, fileName=None, string=None, out=None, printNotRead=True):
"""Function that performs the reading of a LSDyna mesh 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
printNotRead : bool, optional
if True, prints in console the lines dot understood by the reader, by default True
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 = Mesh()
else:
res = out
filetointernalid = {}
oidToElementContainer = {}
oidToLocalElementNumber = {}
l = self.ReadCleanLine()
originalIds = []
nodes = []
nodeSetCounter = 0
while True:
# premature EOF
if l is None:
print("ERROR premature EOF: please check the integrity of your .k file") # pragma: no cover
break # pragma: no cover
# if len(l) == 0: l = string.readline().strip('\n').lstrip().rstrip(); continue
if l.find("*ELEMENT") > -1:
while True:
l = self.ReadCleanLine()
if l.find("*") > -1:
break
s = LineToListNoQuote(l)
n = ListToNumber(s[2:])
try:
nametype = LSDynaNumber[n]
except KeyError: # pragma: no cover
raise RuntimeError("Elements with " + str(n) + "vertices not compatible with reader")
conn = [x for x in map(int, s[2:6])]
elements = res.GetElementsOfType(nametype)
oid = int(s[0])
cpt = elements.AddNewElement(conn, oid)
oidToElementContainer[oid] = elements
oidToLocalElementNumber[oid] = cpt
elTag = "canonical:" + s[1]
elements.tags.CreateTag(elTag, False).AddToTag(cpt - 1)
continue # pragma: no cover # unseen by coverage peephole optimization
if l.find("*NODE") > -1:
dim = 3
s = None
cpt = 0
while True:
l = self.ReadCleanLine()
if l.find("*") > -1:
break
s = LineToListNoQuote(l)
oid = int(s[0])
filetointernalid[oid] = cpt
originalIds.append(oid)
nodes.append(list(map(float, s[1 : dim + 1])))
cpt += 1
continue # pragma: no cover # unseen by coverage peephole optimization
if l.find("*SET_NODE_LIST") > -1:
tag = res.GetNodalTag(str(nodeSetCounter))
nodeSetCounter += 1
self.ReadCleanLine()
while True:
l = self.ReadCleanLine()
if l.find("*") > -1:
break
s = np.array(l.split(), dtype=int)
for oid in s[s > 0]:
tag.AddToTag(int(oid))
continue # pragma: no cover # unseen by coverage peephole optimization
if l.find("*ED.") > -1:
Debug("End file")
break
# case not treated
if printNotRead == True:
Info("line starting with <<" + l + ">> not considered in the reader")
l = self.ReadCleanLine()
continue
self.EndReading()
res.nodes = np.array(nodes, dtype=MuscatFloat)
res.nodes.shape = (cpt, dim)
res.originalIDNodes = np.array(originalIds, dtype=MuscatIndex)
def updateIDsFunc(x):
return filetointernalid[x]
for tag in res.nodesTags:
tag.SetIds(np.vectorize(updateIDsFunc)(tag.GetIds()))
for _, data in res.elements.items():
data.Tighten()
data.connectivity = np.vectorize(updateIDsFunc)(data.connectivity)
res.PrepareForOutput()
return res
RegisterReaderClass(".k", LSDynaReader)
[docs]
def CheckIntegrity():
data = """
$# LS-DYNA Keyword file created by LS-PrePost(R) V4.5.0
*KEYWORD
*TITLE
*ELEMENT_SOLID
$# eid pid n1 n2 n3 n4 n5 n6 n7 n8
1 3000001 1 2 3 4 4 4 4 4
*SET_NODE_LIST
$# sid da1 da2 da3 da4 solver
1 0.0 0.0 0.0 0.0MECH
$# nid1 nid2 nid3 nid4 nid5 nid6 nid7 nid8
1 2 3 4 0 0 0 0
*SET_NODE_LIST
$# sid da1 da2 da3 da4 solver
1 0.0 0.0 0.0 0.0MECH
$# nid1 nid2 nid3 nid4 nid5 nid6 nid7 nid8
1 3 0 0 0 0 0 0
*NODE
$# nid x y z tc rc
1 0.0 0.0 0.0 0 0
2 0.6 0.0 0.0 0 0
3 0.6 0.7 0.0 0 0
4 0.2 0.2 0.3 0 0
5 0.3 0.0 0.1 0 0
*ED.
"""
res = ReadLSDyna(string=data)
res = ReadLSDyna(string=data, out=Mesh())
print(res)
return "ok"
if __name__ == "__main__":
print(CheckIntegrity()) # pragma: no cover