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
from Muscat.Containers.Mesh import Mesh
from Muscat.IO.ReaderBase import ReaderBase
from Muscat.Helpers.Logger import Debug, Info

LSDynaNumber = {4: "tet4"}  # 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