# -*- 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.
#
"""Ansys Workbench Mechanical input file reader
"""
import numpy as np
import Muscat.Containers.ElementsDescription as ED
import Muscat.Containers.Mesh as UM
from Muscat.IO.ReaderBase import ReaderBase
from Muscat.Helpers.LocalVariables import LocalVariables
from Muscat.Types import MuscatIndex, MuscatFloat
from Muscat.IO.AnsysTools import PermutationAnsysToMuscat
[docs]def ReadAnsys(fileName:str="", string:str="", out=None, **kwargs):
"""Function API for reading an Ansys result file
Parameters
----------
fileName : str, optional
name of the file to be read, by default ""
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 = AnsysReader()
reader.SetFileName(fileName)
reader.SetStringToRead(string)
return reader.Read(fileName=fileName, string=string, out=out, **kwargs)
[docs]class AnsysReader(ReaderBase):
"""Ansys Reader class
"""
def __init__(self):
super().__init__()
self.commentHeader = '!'
self.readFormat = 'r'
self.encoding = "latin-1"
[docs] def Read(self, fileName=None, string=None, out=None):
"""Function that performs the reading of an Ansys result 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)
with self.GetIterator() as iterator:
session = Session(iterator, out)
result = session.GetMesh()
result.PrepareForOutput()
return result
[docs] def GetIterator(self):
return InputContextManager(self)
[docs]class InputContextManager:
def __init__(self, reader):
self.reader = reader
def __enter__(self):
self.reader.StartReading()
return InputIterator(self.reader)
def __exit__(self, exc_type, exc_value, traceback):
self.reader.EndReading()
return False
[docs]class Session:
def __init__(self, iterator, out=None):
self.iterator = iterator
self.result = UM.Mesh() if out is None else out
self.block_count = 0
self.CSDict = {} # to store co
# Nodes
self.result.nodes = np.empty((0, 3), dtype=np.double)
self.result.originalIDNodes = np.empty((0,), dtype=MuscatIndex)
self.node_count = 0
self.node_rank_from_id = dict()
# Elements
self.element_type_and_rank_from_id = dict()
self.element_type_ids = dict() # Local to global element type numbering
self.current_element_type = None
self.elementSelectoin = None
# Variables
self.substitutions = LocalVariables(prePostChars=('',''))
commands = {
'*set': self.ParseAssignment,
'nblock': self.ParseNodeBlock,
'eblock': self.ParseElementBlock,
'en': self.ParseUnblockedElement,
'et': self.ParseElementTypeDefinition,
'type': self.ParseElementTypeSelection,
'CMBLOCK': self.ParseTagDefinition,
'esel': self.ParseEselDefinition,
'cm': self.ParseCMDefinition,
'*Get':self.ParseGet,
'N': self.ParseN,
'CS': self.ParseCS,
'local': self.ParseLocal,
'EMODIF': self.ParseEMODIF,
'emod': self.ParseEMODIF,
}
def Pass(args): pass
for multiline in self.iterator:
lines = multiline.split('$')
for line in lines:
line = line.strip()
tokens = line.split(',')
keyword = tokens[0]
arguments = [x.strip() for x in tokens[1:]]
commands.get(keyword, Pass)(arguments)
[docs] def ParseAssignment(self, args):
self.substitutions.SetVariable(args[0], args[1])
[docs] def ParseGet(self, args):
#https://www.mm.bme.hu/~gyebro/files/ans_help_v182/ans_cmd/Hlp_C_GET.html#get.prep.node
par = str(args[0]) # The name of the resulting parameter. See *SET for name restrictions.
entity = str(args[1]) # Entity keyword. Valid keywords are NODE, ELEM, KP, LINE, AREA, VOLU, etc., as shown for Entity = in the tables below.
ED.NUM = int(args[2]) # The number or label for the entity (as shown for ED.NUM = in the tables below). In some cases, a zero (or blank) ED.NUM represents all entities of the set.
Item1 = str(args[3]) # The name of a particular item for the given entity. Valid items are as shown in the Item1 columns of the tables below.
IT1NUM = str([4]) # The number (or label) for the specified Item1 (if any). Valid IT1NUM values are as shown in the IT1NUM columns of the tables below. Some Item1 labels do not require an IT1NUM value.
if len(args) >5 :
Item2 = str(args[5]) # A second set of item labels and numbers to further qualify the item for which data are to be retrieved. Most items do not require this level of information.
IT2NUM = str([6])
if entity == "NODE" and ED.NUM == 0 and Item1 == "NUM" and IT1NUM == "MAXD":
#normaly I must use the max id node
self.substitutions.SetVariable(par,self.result.nodes.shape[0])
else:
return
[docs] def ParseN(self,args):
NID= (self.substitutions.Apply(args[0]))
NX = float(self.substitutions.Apply(args[1]))
NY = float(self.substitutions.Apply(args[2]))
NZ = float(self.substitutions.Apply(args[3]))
self.CSDict["_Internal_N_"+NID] = [NX,NY,NZ]
[docs] def ParseCS(self,args):
KCN = int(args[0]) # Arbitrary reference number assigned to this coordinate system. Must be greater than 10. A coordinate system previously defined with this number will be redefined.
KCS = args[1] # Coordinate system type: 0 or CART - Cartesian
# 1 or CYLIN - Cylindrical (circular or elliptical)
# 2 or SPHE — Spherical (or spheroidal)
# 3 or TORO — Toroidal
NORIG = self.CSDict["_Internal_N_"+self.substitutions.Apply(args[2])] # Node defining the origin of this coordinate system. If NORIG = P, graphical picking is enabled and all remaining command fields are ignored (valid only in the GUI).
NXAX = self.CSDict["_Internal_N_"+self.substitutions.Apply(args[3])] # Node defining the positive x-axis orientation of this coordinate system.
NXYPL = self.CSDict["_Internal_N_"+self.substitutions.Apply(args[4])] # Node defining the x-y plane (with NORIG and NXAX) in the first or second quadrant of this coordinate system.
if len(args) > 5:
PAR1 = args[5] # Used for elliptical, spheroidal, or toroidal systems. If KCS = 1 or 2, PAR1 is the ratio of the ellipse Y-axis radius to X-axis radius (defaults to 1.0 (circle)). If KCS = 3, PAR1 is the major radius of the torus.
PAR2 = args[6] # Used for spheroidal systems. If KCS = 2, PAR2 = ratio of ellipse Z-axis radius to X-axis radius (defaults to 1.0 (circle)).
if KCS == "0" or KCS == "CART":
origin =np.array(NORIG)
V0 = np.array(NXAX)
V0 /= np.linalg.norm(V0)
V1 = np.array(NXYPL)
V1 -= np.dot(V0,V1)*V0
V1 /= np.linalg.norm(V1)
self.CSDict[KCN] = [origin, V0,V1]
else:
raise
[docs] def ParseLocal(self, args):
"""
Defines a local coordinate system by a location and orientation.
https://www.mm.bme.hu/~gyebro/files/ans_help_v182/ans_cmd/Hlp_C_LOCAL.html
local,19,0,1.00000000000001,3.,3.,90.00000010284,-3.47873168682575e-013,90.0000001028399
"""
KCN = int(args[0]) # Arbitrary reference number assigned to this coordinate system. Must be greater than 10. A coordinate system previously defined with this number will be redefined.
KCS = args[1]
XC, YC, ZC = map(MuscatFloat, args[2:5])
THXY = MuscatFloat(args[5])
THYZ = MuscatFloat(args[6])
THZX = MuscatFloat(args[7])
if KCS in ["1", "2", "3", "CYLIN", "SPHE", "TORO"]:
raise RuntimeError(f"local no implemented for {KCS}")
else:
THXY = np.radians(THXY)
THYZ = np.radians(THYZ)
THZX = np.radians(THZX)
ctheta, stheta = np.cos(THXY), np.sin(THXY)
cphi, sphi = np.cos(THYZ), np.sin(THYZ)
cpsi, spsi = np.cos(THZX), np.sin(THZX)
rotX = np.array([[1, 0, 0],
[0, cphi, -sphi],
[0, sphi, cphi]])
rotY = np.array([[ cpsi, 0, spsi],
[ 0, 1, 0],
[-spsi, 0, cpsi]])
rotZ = np.array([[ctheta, -stheta, 0],
[stheta, ctheta, 0],
[ 0, 0, 1]])
rotation = rotY @ rotX @ rotZ
self.CSDict[KCN] = [ np.array([XC, YC, ZC], dtype=MuscatFloat),
rotation[:,0], rotation[:,1]]
[docs] def ParseEMODIF(self, args):
# https://www.mm.bme.hu/~gyebro/files/ans_help_v182/ans_cmd/Hlp_C_EMODIF.html
# emod, 8, esys, 19
IEL = args[0] #Modify nodes and/or attributes for element number IEL. If ALL, modify all selected elements [ESEL]. If IEL = P, graphical picking is enabled and all remaining command fields are ignored (valid only in the GUI). A component name may also be substituted for IEL.
STLOC = args[1]
if "V0" not in self.result.elemFields:
self.result.elemFields["origin"] = np.zeros((self.result.GetNumberOfElements(),3), dtype=MuscatFloat )
self.result.elemFields["V0"] = np.zeros((self.result.GetNumberOfElements(),3), dtype=MuscatFloat )
self.result.elemFields["V0"][:,0:3] = [1,0,0]
self.result.elemFields["V1"] = np.zeros((self.result.GetNumberOfElements(),3), dtype=MuscatFloat )
self.result.elemFields["V1"][:,0:3] = [0,1,0]
if STLOC.lower() == "esys":
I1 = int(args[2])
element_type, rank = self.element_type_and_rank_from_id[int(IEL)]
container = self.result.GetElementsOfType(element_type)
globaloffset = self.result.ComputeGlobalOffset()
origin, V0, V1 = self.CSDict[I1]
self.result.elemFields["origin"][globaloffset[container.elementType] + rank,:] = origin
self.result.elemFields["V0"][globaloffset[container.elementType] + rank,:] = V0
self.result.elemFields["V1"][globaloffset[container.elementType] + rank,:] = V1
print(self.result.elemFields["V0"])
[docs] def ParseNodeBlock(self, args):
# Arguments: NUMFIELD,[Solkey,NDMAX[,NDSEL]]
field_count = int(args[0])
solid_key = args[1] if len(args) > 1 else ''
max_new_node_count = int(args[2]) if len(args) > 2 else 1
assert(field_count == 3)
assert(solid_key == '')
expected_node_count = self.node_count + max_new_node_count
oldNodes = self.result.nodes
self.result.nodes = np.zeros((expected_node_count,3))
self.result.nodes[0:oldNodes.shape[0],:] = oldNodes
oldOriginalIDNodes = self.result.originalIDNodes
self.result.originalIDNodes = np.zeros(expected_node_count,dtype=int)
self.result.originalIDNodes[0:oldOriginalIDNodes.shape[0]] = oldOriginalIDNodes
# Skip format line
line = next(self.iterator)
while True:
line = next(self.iterator)
if line.startswith('-1'):
break
tokens = line.split()
node_id = int(tokens[0])
self.node_rank_from_id[node_id] = self.node_count
self.result.originalIDNodes[self.node_count] = node_id
self.result.nodes[self.node_count, :] = [float(t) for t in tokens[1:]]
self.node_count += 1
self.result.nodes = self.result.nodes[0:self.node_count,:]
self.result.originalIDNodes = self.result.originalIDNodes[0:self.node_count]
[docs] def ParseElementBlock(self, args):
# Arguments: NUM_NODES,Solkey[,,count]
# int(args[0]) -> num_nodes: Cannot be trusted
solid_key = args[1]
max_element_count = int(args[3])
# Skip format line
line = next(self.iterator)
if solid_key == 'solid':
self.ReadSolidEblock(max_element_count)
else:
self.ReadNonSolidEblock(max_element_count)
self.block_count += 1
[docs] def ParseUnblockedElement(self, args):
et = self.current_element_type
assert(self.element_type_ids[et] in ('170', '201'))
element_id = int(args[0])
node_id = int(self.substitutions.Apply(args[1]))
node_rank = self.node_rank_from_id[node_id]
elements = self.result.GetElementsOfType(ED.Point_1)
internal_count = elements.AddNewElement([node_rank], element_id)
internal_rank = internal_count - 1
self.element_type_and_rank_from_id[element_id] = (ED.Point_1, internal_rank)
auto_etag = 'et_{}'.format(et)
elements.AddElementToTag(auto_etag, internal_rank)
# Figure out a nodal tag name from the element id
auto_ntag = 'elem_{}'.format(element_id)
tag = self.result.nodesTags.CreateTag(auto_ntag)
tag.SetIds([self.node_rank_from_id[node_id]])
[docs] def ParseElementTypeDefinition(self, args):
et = int(self.substitutions.Apply(args[0]))
self.element_type_ids[et] = args[1]
[docs] def ParseElementTypeSelection(self, args):
et = int(self.substitutions.Apply(args[0]))
self.current_element_type = et
[docs] def ParseCMDefinition(self,args):
# cm,PEAU_MAT_COMPOSITE_SKIN_SPAR_B_3,elem
if args[1].lower() != "elem":
return
tagname = args[0]
for selection in self.elementSelection:
for names, data in self.result.elements.items():
if selection in data.tags:
data.tags.CreateTag(tagname,False).AddToTag(data.tags[selection].GetIds())
[docs] def ParseEselDefinition(self,args):
# esel,s,type,,2
# esel,a,type,,3,18
# esel,a,type,,22,29
if args[0].lower() == "none":
self.elementSelection = []
return
if args[0].lower() == "all":
self.elementSelection = None
return
if args[0].lower() == "s":
self.elementSelection = []
elif args[0].lower() == "a":
pass
if args[1].lower() =="type":
VMIN = int(args[3])
if len(args) > 4:
VMAX = int(args[4])
else:
VMAX = VMIN
if len(args) > 5:
VINC = int(args[5])
else:
VINC = 1
for et in range(VMIN,VMAX+1,VINC):
self.elementSelection.append(f"et_{et}")
[docs] def ParseTagDefinition(self, args):
tag_name = args[0].strip()
kind = args[1]
item_count = int(args[2])
items_per_line = 8
full_line_count = item_count // items_per_line
remainder = item_count % items_per_line
line_count = full_line_count if remainder == 0 \
else full_line_count + 1
# Skip format line
line = next(self.iterator)
items = list()
for i in range(line_count):
line = next(self.iterator)
items.extend((int(t) for t in line.split()))
if kind == 'NODE':
tag = self.result.nodesTags.CreateTag(tag_name)
tag.SetIds([self.node_rank_from_id[n] for n in items])
else:
assert(kind in ('ELEMENT','ELEM') )
for element_id in items:
element_type, rank = self.element_type_and_rank_from_id[element_id]
container = self.result.GetElementsOfType(element_type)
container.AddElementToTag(rank, tag_name)
[docs] def GetMesh(self):
return self.result
[docs] def ReadEblock(self, data_parser, max_element_count):
element_rank = 0
while True:
line = next(self.iterator)
if line.startswith('-1'):
break
assert(element_rank < max_element_count)
tokens = line.split()
values = [int(t) for t in tokens]
element_id, et, real_constant, _, nodes = \
data_parser(values, self.iterator)
element_type_id = self.element_type_ids[et]
internal_element_type, unique_nodes = \
internal_element_type_from_ansys[element_type_id](nodes)
connectivity = [self.node_rank_from_id[n] for n in unique_nodes]
elements = self.result.GetElementsOfType(internal_element_type)
internal_count = elements.AddNewElement(connectivity, element_id)
internal_rank = internal_count - 1
self.element_type_and_rank_from_id[element_id] = \
(internal_element_type, internal_rank)
auto_etags = (
'et_{}'.format(et),
'rc_{}'.format(real_constant),
'EB_{}'.format(self.block_count))
for t in auto_etags:
elements.AddElementToTag(t, internal_rank)
element_rank += 1
[docs] def ReadSolidEblock(self, max_element_count):
def SolidDataParser(values, it):
material_id = values[0]
et = values[1]
real_constant = values[2]
element_id = values[10]
element_node_count = values[8]
if element_node_count > 8:
overflow = next(it)
values.extend((int (t) for t in overflow.split()))
nodes = values[11:11+element_node_count]
return (element_id, et, real_constant, material_id, nodes)
self.ReadEblock(SolidDataParser, max_element_count)
[docs] def ReadNonSolidEblock(self, max_element_count):
def NonSolidDataParser(values, _):
element_id = values[0]
et = values[1]
real_constant = values[2]
material_id = values[3]
nodes = values[5:]
return (element_id, et, real_constant, material_id, nodes)
self.ReadEblock(NonSolidDataParser, max_element_count)
[docs]def discriminate_tri_or_quad(nodes):
# SURF154/TARGE170/CONTA174: ED.Quadrangle_4 or ED.Quadrangle_9
# May degenerate to ED.Triangle_3 or ED.Triangle_6
# Node numbering: ijklmnop
repeated_kl = nodes[2] == nodes[3]
from itertools import compress
if len(nodes) == 4:
if repeated_kl:
internal_element_type = ED.Triangle_3
unique_nodes = nodes[:-1]
else:
internal_element_type = ED.Quadrangle_4
unique_nodes = nodes
else:
assert(len(nodes) == 8)
if repeated_kl:
assert(nodes[2] == nodes[6])
internal_element_type = ED.Triangle_6
unique_nodes = list(compress(nodes, (1, 1, 1, 0, 1, 1, 0, 1)))
else:
internal_element_type = ED.Quadrangle_8
unique_nodes = nodes
return internal_element_type, unique_nodes
[docs]def discriminate_shell181(nodes):
return discriminate_tri_or_quad(nodes)
[docs]def discriminate_solid185(nodes):
# SOLID185: ED.Hexahedron_8
# May degenerate to ED.Wedge_6, ED.Pyramid_5 or ED.Tetrahedron_4
# Node numbering: ijklmnop
repeated_kl = nodes[2] == nodes[3]
repeated_mn = nodes[4] == nodes[5]
repeated_op = nodes[6] == nodes[7]
from itertools import compress
if repeated_op:
if repeated_mn:
if repeated_kl:
internal_element_type = ED.Tetrahedron_4
unique_nodes = compress(nodes, (1, 1, 1, 0, 1))
else:
internal_element_type = ED.Pyramid_5
unique_nodes = compress(nodes, (1, 1, 1, 1, 1))
else:
internal_element_type = ED.Wedge_6
unique_nodes = compress(nodes, (1, 1, 1, 0, 1, 1, 1))
else:
internal_element_type = ED.Hexahedron_8
unique_nodes = nodes
return internal_element_type, list(unique_nodes)
[docs]def discriminate_solid186(nodes):
# SOLID186: ED.Hexahedron_20
# May degenerate to ED.Wedge_15, ED.Pyramid_13 or ED.Tetrahedron_10
# Node numbering: ijklmnopqrstuvwxyzab
repeated_kl = nodes[2] == nodes[3]
repeated_mn = nodes[4] == nodes[5]
repeated_op = nodes[6] == nodes[7]
from itertools import compress
if repeated_op:
if repeated_mn:
if repeated_kl:
assert(nodes[4] == nodes[6])
assert(nodes[6] == nodes[12])
assert(nodes[6] == nodes[13])
assert(nodes[6] == nodes[14])
assert(nodes[6] == nodes[15])
assert(nodes[18] == nodes[19])
assert(nodes[2] == nodes[10])
internal_element_type = ED.Tetrahedron_10
unique_nodes = list(compress(nodes, (1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0)))
nodes = [ nodes[per] for per in PermutationAnsysToMuscat[ED.Tetrahedron_10] ]
else:
assert(nodes[4] == nodes[6])
assert(nodes[6] == nodes[12])
assert(nodes[6] == nodes[13])
assert(nodes[6] == nodes[14])
assert(nodes[6] == nodes[15])
internal_element_type = ED.Pyramid_13
unique_nodes = list(compress(nodes, (1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1)))
else:
assert(nodes[6] == nodes[14])
assert(nodes[18] == nodes[19])
assert(nodes[2] == nodes[10])
internal_element_type = ED.Wedge_15
unique_nodes = list(compress(nodes, (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0)))
else:
internal_element_type = ED.Hexahedron_20
unique_nodes = nodes
return internal_element_type, unique_nodes
[docs]def discriminate_solid187(nodes):
internal_element_type = ED.Tetrahedron_10
nodes = [ nodes[per] for per in PermutationAnsysToMuscat[ED.Tetrahedron_10] ]
return internal_element_type, nodes
# FOLLW201 is a one-node 3d element used to apply nodal forces
internal_element_type_from_ansys = {
'170': discriminate_tri_or_quad,
'174': discriminate_tri_or_quad,
'154': discriminate_tri_or_quad,
'181': discriminate_shell181,
'185': discriminate_solid185,
'186': discriminate_solid186,
'187': discriminate_solid187
}
from Muscat.IO.IOFactory import RegisterReaderClass
RegisterReaderClass(".ansys", AnsysReader)
[docs]def CheckIntegrity():
__teststring = u"""
nblock,3,,44
(1i9,3e20.9e3)
551 7.784032421E-02 6.661491953E-02 2.000000000E-01
1691 8.991484887E-02 6.820190681E-02 1.903279204E-01
1944 7.455965603E-02 6.107661302E-02 1.906569403E-01
2111 9.395317480E-02 5.598013490E-02 1.886333684E-01
2218 8.604121057E-02 6.526570146E-02 1.798559428E-01
2233 8.587154519E-02 5.451195787E-02 1.957137802E-01
4975 8.387758654E-02 6.740841317E-02 1.951639602E-01
4976 7.619999012E-02 6.384576627E-02 1.953284701E-01
4978 8.185593470E-02 6.056343870E-02 1.978568901E-01
6782 7.261344291E-04 -6.938080072E-04 7.640761699E-02
6805 2.186338673E-04 -8.078558619E-04 7.646145635E-02
7308 6.305392899E-04 -2.000856285E-04 7.594041518E-02
7309 1.108636472E-04 -3.288991121E-04 7.599344534E-02
7859 1.725123756E-04 -7.844719866E-04 7.599047369E-02
7860 7.591255417E-04 -7.164507578E-04 7.593581544E-02
8108 1.476547648E-04 -3.576023233E-04 7.647352256E-02
8111 6.989548354E-04 -2.490909499E-04 7.643098938E-02
11353 8.223725245E-02 6.463925992E-02 1.904924303E-01
11355 9.193401184E-02 6.209102085E-02 1.894806444E-01
11357 8.797802972E-02 6.673380414E-02 1.850919316E-01
11358 8.789319703E-02 6.135693234E-02 1.930208503E-01
12938 8.030043330E-02 6.317115724E-02 1.852564415E-01
12939 8.021560061E-02 5.779428544E-02 1.931853602E-01
13639 8.999719269E-02 6.062291818E-02 1.842446556E-01
13640 8.991236000E-02 5.524604638E-02 1.921735743E-01
13703 8.595637788E-02 5.988882967E-02 1.877848615E-01
32654 -1.274217310E+01 3.840702614E+01 -1.612452772E+01
37816 -1.334739993E+01 3.905933630E+01 -1.603912279E+01
37856 -1.364793556E+01 3.797073871E+01 -1.607483826E+01
39901 -1.425619495E+01 3.874218666E+01 -1.561731625E+01
42378 -1.371046977E+01 3.892752029E+01 -1.493156312E+01
45628 4.723841482E-04 -7.508319345E-04 7.643453667E-02
45632 7.426299854E-04 -7.051293825E-04 7.617171621E-02
45633 7.125446322E-04 -4.714494786E-04 7.641930319E-02
45769 1.955731215E-04 -7.961639242E-04 7.622596502E-02
45770 1.831443160E-04 -5.827290926E-04 7.646748946E-02
47969 3.707014685E-04 -2.644923703E-04 7.596693026E-02
47970 6.948324158E-04 -4.582681931E-04 7.593811531E-02
47971 6.647470626E-04 -2.245882892E-04 7.618570228E-02
47973 1.416880114E-04 -5.566855494E-04 7.599195951E-02
47974 1.292592060E-04 -3.432507177E-04 7.623348395E-02
50074 4.658189586E-04 -7.504613722E-04 7.596314456E-02
50908 4.233048001E-04 -3.033466366E-04 7.645225597E-02
62174 -1.331961824E+01 3.837984154E+01 -1.550789885E+01
-1
et,1,185
eblock,19,solid,,340744
(19i9)
1 1 1 1 0 0 0 0 8 0 1 37816 39901 62174 62174 42378 42378 42378 42378
1 1 1 1 0 0 0 0 8 0 2 37816 37856 62174 62174 39901 39901 39901 39901
1 1 1 1 0 0 0 0 8 0 3 32654 62174 37816 37816 37856 37856 37856 37856
-1
CMBLOCK,FewNodes,NODE, 2
(8i10)
37856 37816
et,2,187
eblock,19,solid,,3
(19i9)
1 2 1 1 0 0 0 0 10 0 1 1691 2233 1944 2218 11358 12939 11353 11357
13703 12938
1 2 1 1 0 0 0 0 10 0 2 1691 2111 2233 2218 11355 13640 11358 11357
13639 13703
1 2 1 1 0 0 0 0 10 0 3 551 1691 2233 1944 4975 11358 4978 4976
11353 12939
-1
*set,tid,3
et,tid,154
eblock,10,,,2
(15i9)
10915 3 4 3 12 551 1691 2233 2233 4975 11358 2233 4976
10916 3 5 3 12 1691 2233 1944 1944 11358 12939 1944 11357
-1
et,4,186
eblock,19,solid,,4
(19i9)
3 4 1 3 0 0 0 0 20 0 1 6782 7860 7859 6805 8111 7308 7309 8108
45632 50074 45769 45628 47971 47969 47974 50908 45633 47970 47973 45770
3 4 1 3 0 0 0 0 20 0 2 6782 7860 7859 7859 8111 8111 8111 8111
45632 50074 7859 45628 8111 8111 8111 8111 45633 47970 47973 47973
3 4 1 3 0 0 0 0 20 0 3 6782 7860 7859 6805 8111 8111 8111 8111
45632 50074 45769 45628 8111 8111 8111 8111 45633 47970 47973 45770
3 4 1 3 0 0 0 0 20 0 4 6782 7860 7859 7859 8111 7308 7309 7309
45632 50074 7859 45628 47971 47969 7309 50908 45633 47970 47973 47973
-1
local,19,0,1.00000000000001,3.,3.,90.00000010284,-3.47873168682575e-013,90.0000001028399
emod, 1, esys, 19
CSYS,0
"""
res = ReadAnsys(string=__teststring)
print("----")
print('coords: {}'.format(res.nodes))
print('node ids: {}'.format(res.originalIDNodes))
print('hex20: {}'.format((res.GetElementsOfType(ED.ElementType.Hexahedron_20).connectivity)))
print('pyr13: {}'.format((res.GetElementsOfType(ED.ElementType.Pyramid_13).connectivity)))
print('tet4: {}'.format((res.GetElementsOfType(ED.ElementType.Tetrahedron_4).connectivity)))
print('tet10: {}'.format((res.GetElementsOfType(ED.ElementType.Tetrahedron_10).connectivity)))
print('tri6: {}'.format((res.GetElementsOfType(ED.ElementType.Triangle_6).connectivity)))
print('wed15: {}'.format((res.GetElementsOfType(ED.ElementType.Wedge_15).connectivity)))
node_tag = res.GetNodalTag('FewNodes')
print('node set {}: {}'.format(node_tag, node_tag.GetIds()))
for t in ('et_1', 'et_2', 'et_3', 'et_4', 'rc_4', 'rc_5', 'EB_0', 'EB_1', 'EB_2', 'EB_3'):
print('element set {}: {}'.format(t, res.GetElementsInTag(t)))
print(res)
return 'ok'
if __name__ == '__main__':
print(CheckIntegrity())# pragma: no cover