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.Containers.ElementsDescription as ED
from Muscat.Containers.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