diff --git a/_build/doctrees/environment.pickle b/_build/doctrees/environment.pickle index 50ef83a57a..439c59a1bb 100644 Binary files a/_build/doctrees/environment.pickle and b/_build/doctrees/environment.pickle differ diff --git a/_build/doctrees/exodus.doctree b/_build/doctrees/exodus.doctree index 7a8c9a5c2d..18a0dab20f 100644 Binary files a/_build/doctrees/exodus.doctree and b/_build/doctrees/exodus.doctree differ diff --git a/_build/html/_modules/exodus.html b/_build/html/_modules/exodus.html index f20da19485..660b3c5662 100644 --- a/_build/html/_modules/exodus.html +++ b/_build/html/_modules/exodus.html @@ -196,7 +196,7 @@
def _parse_exodus_version(version_string):
if version_string:
- assert version_string.startswith("#define EXODUS_VERSION "), "Received a incorrectly formated verstion string. Please check the CMakeLists.txt"
+ assert version_string.startswith("#define EXODUS_VERSION "), "Received a incorrectly formatted verstion string. Please check the CMakeLists.txt"
return int(version_string.strip().split()[-1].strip('"').replace('.', ''))
else:
return 0
@@ -1663,7 +1663,7 @@ Source code for exodus
[docs] def get_num_map(self, mapType, idx):
"""
get user-defined map of exodus element/node/edge/face index to user- or
- application- defined element/node/edge/face values. Map values are arbitary integers
+ application- defined element/node/edge/face values. Map values are arbitrary integers
>>> elem_num_map = exo.get_num_map('EX_ELEM_MAP', 1)
@@ -1695,7 +1695,7 @@ Source code for exodus
[docs] def put_num_map(self, mapType, idx, num_map):
"""
put user-defined map of exodus element/node/edge/face index to user- or
- application- defined element/node/edge/face values. Map values are arbitary integers
+ application- defined element/node/edge/face values. Map values are arbitrary integers
Parameters
diff --git a/_build/html/_modules/exomerge.html b/_build/html/_modules/exomerge.html
index 54b9d803cd..b89e2b6d44 100644
--- a/_build/html/_modules/exomerge.html
+++ b/_build/html/_modules/exomerge.html
@@ -119,7 +119,9 @@ Source code for exomerge
import operator
if sys.version_info[0] < 3:
- raise Exception("Python-3 version. If using python-2, try `import exomerge2 as exomerge`")
+ raise Exception(
+ "Python-3 version. If using python-2, try `import exomerge2 as exomerge`"
+ )
# import exodus module
# (exodus.py should be in the same directory as this file)
@@ -133,7 +135,7 @@ Source code for exomerge
VERSION = __version__
# contact person for issues
-CONTACT = 'Tim Kostka <tdkostk@sandia.gov>'
+CONTACT = "Tim Kostka <tdkostk@sandia.gov>"
# show the banner on first use
SHOW_BANNER = True
@@ -153,11 +155,12 @@ Source code for exomerge
# is the renamed function, or None.
# e.g. DEPRECATED_FUNCTIONS['build_hex8_cube'] = 'create_hex8_cube'
DEPRECATED_FUNCTIONS = dict()
-DEPRECATED_FUNCTIONS['write'] = 'export'
+DEPRECATED_FUNCTIONS["write"] = "export"
@@ -186,79 +189,117 @@ Source code for exomerge
# define translation from two faces to a 3D cohesive element
COHESIVE_FORMULA = dict()
- COHESIVE_FORMULA['quad4'] = ['hex8', (0, 1, 2, 3, 4, 5, 6, 7)]
- COHESIVE_FORMULA['tri3'] = ['wedge6', (0, 1, 2, 3, 4, 5)]
- COHESIVE_FORMULA['tri6'] = [
- 'wedge12', (0, 1, 2, 6, 7, 8, 3, 4, 5, 9, 10, 11)
- ]
+ COHESIVE_FORMULA["quad4"] = ["hex8", (0, 1, 2, 3, 4, 5, 6, 7)]
+ COHESIVE_FORMULA["tri3"] = ["wedge6", (0, 1, 2, 3, 4, 5)]
+ COHESIVE_FORMULA["tri6"] = ["wedge12", (0, 1, 2, 6, 7, 8, 3, 4, 5, 9, 10, 11)]
# define calculation for element length/area/volume
VOLUME_FORMULA = dict()
- VOLUME_FORMULA['line2'] = [1.0, (0, 1)]
- VOLUME_FORMULA['line3'] = VOLUME_FORMULA['line2']
- VOLUME_FORMULA['tri3'] = [0.5, (0, 1), (0, 2)]
- VOLUME_FORMULA['tri6'] = VOLUME_FORMULA['tri3']
- VOLUME_FORMULA['quad4'] = [0.5, (0, 2), (1, 3)]
- VOLUME_FORMULA['quad6'] = VOLUME_FORMULA['quad4']
- VOLUME_FORMULA['quad8'] = VOLUME_FORMULA['quad4']
- VOLUME_FORMULA['tet4'] = [1.0 / 6.0, (0, 1), (0, 2), (0, 3)]
- VOLUME_FORMULA['tet10'] = VOLUME_FORMULA['tet4']
- VOLUME_FORMULA['wedge6'] = [
- 0.5, ((0, 3), (1, 4)), ((0, 3), (2, 5)), ((0, 1, 2), (3, 4, 5))
+ VOLUME_FORMULA["line2"] = [1.0, (0, 1)]
+ VOLUME_FORMULA["line3"] = VOLUME_FORMULA["line2"]
+ VOLUME_FORMULA["tri3"] = [0.5, (0, 1), (0, 2)]
+ VOLUME_FORMULA["tri6"] = VOLUME_FORMULA["tri3"]
+ VOLUME_FORMULA["quad4"] = [0.5, (0, 2), (1, 3)]
+ VOLUME_FORMULA["quad6"] = VOLUME_FORMULA["quad4"]
+ VOLUME_FORMULA["quad8"] = VOLUME_FORMULA["quad4"]
+ VOLUME_FORMULA["tet4"] = [1.0 / 6.0, (0, 1), (0, 2), (0, 3)]
+ VOLUME_FORMULA["tet10"] = VOLUME_FORMULA["tet4"]
+ VOLUME_FORMULA["wedge6"] = [
+ 0.5,
+ ((0, 3), (1, 4)),
+ ((0, 3), (2, 5)),
+ ((0, 1, 2), (3, 4, 5)),
]
- VOLUME_FORMULA['wedge12'] = VOLUME_FORMULA['wedge6']
- VOLUME_FORMULA['wedge15'] = VOLUME_FORMULA['wedge6']
- VOLUME_FORMULA['wedge16'] = VOLUME_FORMULA['wedge6']
- VOLUME_FORMULA['hex8'] = [
- 1.0, ((0, 3, 4, 7), (1, 2, 5, 6)), ((0, 1, 4, 5), (2, 3, 6, 7)),
- ((0, 1, 2, 3), (4, 5, 6, 7))
+ VOLUME_FORMULA["wedge12"] = VOLUME_FORMULA["wedge6"]
+ VOLUME_FORMULA["wedge15"] = VOLUME_FORMULA["wedge6"]
+ VOLUME_FORMULA["wedge16"] = VOLUME_FORMULA["wedge6"]
+ VOLUME_FORMULA["hex8"] = [
+ 1.0,
+ ((0, 3, 4, 7), (1, 2, 5, 6)),
+ ((0, 1, 4, 5), (2, 3, 6, 7)),
+ ((0, 1, 2, 3), (4, 5, 6, 7)),
]
- VOLUME_FORMULA['hex20'] = VOLUME_FORMULA['hex8']
+ VOLUME_FORMULA["hex20"] = VOLUME_FORMULA["hex8"]
# define mapping of the external faces of an element
FACE_MAPPING = dict()
- FACE_MAPPING['hex8'] = [('quad4', (0, 1, 5, 4)), ('quad4', (1, 2, 6, 5)),
- ('quad4', (2, 3, 7, 6)), ('quad4', (3, 0, 4, 7)),
- ('quad4', (0, 3, 2, 1)), ('quad4', (4, 5, 6, 7))]
- FACE_MAPPING['hex20'] = [('quad8', (0, 1, 5, 4, 8, 13, 16, 12)),
- ('quad8', (1, 2, 6, 5, 9, 14, 17, 13)),
- ('quad8', (2, 3, 7, 6, 10, 15, 18, 14)),
- ('quad8', (3, 0, 4, 7, 11, 12, 19, 15)),
- ('quad8', (0, 3, 2, 1, 11, 10, 9, 8)),
- ('quad8', (4, 5, 6, 7, 16, 17, 18, 19))]
- FACE_MAPPING['tet4'] = [('tri3', (0, 1, 3)), ('tri3', (1, 2, 3)),
- ('tri3', (2, 0, 3)), ('tri3', (0, 2, 1))]
- FACE_MAPPING['tet10'] = [('tri6', (0, 1, 3, 4, 8, 7)),
- ('tri6', (1, 2, 3, 5, 9, 8)),
- ('tri6', (2, 0, 3, 6, 7, 9)),
- ('tri6', (0, 2, 1, 6, 5, 4))]
- FACE_MAPPING['wedge6'] = [('quad4', (0, 1, 4, 3)), ('quad4', (1, 2, 5, 4)),
- ('quad4', (2, 0, 3, 5)), ('tri3', (0, 2, 1)),
- ('tri3', (3, 4, 5))]
- FACE_MAPPING['wedge12'] = [('quad6', (0, 1, 4, 3, 6, 9)),
- ('quad6', (1, 2, 5, 4, 7, 10)),
- ('quad6', (2, 0, 3, 5, 8, 11)),
- ('tri6', (0, 2, 1, 8, 7, 6)),
- ('tri6', (3, 4, 5, 11, 10, 9))]
- FACE_MAPPING['wedge15'] = [('quad8', (0, 1, 4, 3, 6, 10, 12, 9)),
- ('quad8', (1, 2, 5, 4, 7, 11, 13, 10)),
- ('quad8', (2, 0, 3, 5, 8, 9, 14, 11)),
- ('tri6', (0, 2, 1, 8, 7, 6)),
- ('tri6', (3, 4, 5, 12, 13, 14))]
- FACE_MAPPING['wedge16'] = FACE_MAPPING['wedge15']
- FACE_MAPPING['tri3'] = [('line2', (0, 1)), ('line2', (1, 2)),
- ('line2', (2, 0))]
- FACE_MAPPING['tri6'] = [('line3', (0, 1, 3)), ('line3', (1, 2, 4)),
- ('line3', (2, 0, 5))]
- FACE_MAPPING['quad4'] = [('line2', (0, 1)), ('line2', (1, 2)),
- ('line2', (2, 3)), ('line2', (3, 0))]
- FACE_MAPPING['quad6'] = [('line3', (0, 1, 4)), ('line2', (1, 2)),
- ('line3', (2, 5, 3)), ('line2', (3, 0))]
- FACE_MAPPING['quad8'] = [('line3', (0, 1, 4)), ('line3', (1, 2, 5)),
- ('line3', (2, 3, 6)), ('line3', (3, 0, 7))]
- FACE_MAPPING['line2'] = [('point', tuple([0])), ('point', tuple([1]))]
- FACE_MAPPING['line3'] = FACE_MAPPING['line2']
- FACE_MAPPING['point'] = []
+ FACE_MAPPING["hex8"] = [
+ ("quad4", (0, 1, 5, 4)),
+ ("quad4", (1, 2, 6, 5)),
+ ("quad4", (2, 3, 7, 6)),
+ ("quad4", (3, 0, 4, 7)),
+ ("quad4", (0, 3, 2, 1)),
+ ("quad4", (4, 5, 6, 7)),
+ ]
+ FACE_MAPPING["hex20"] = [
+ ("quad8", (0, 1, 5, 4, 8, 13, 16, 12)),
+ ("quad8", (1, 2, 6, 5, 9, 14, 17, 13)),
+ ("quad8", (2, 3, 7, 6, 10, 15, 18, 14)),
+ ("quad8", (3, 0, 4, 7, 11, 12, 19, 15)),
+ ("quad8", (0, 3, 2, 1, 11, 10, 9, 8)),
+ ("quad8", (4, 5, 6, 7, 16, 17, 18, 19)),
+ ]
+ FACE_MAPPING["tet4"] = [
+ ("tri3", (0, 1, 3)),
+ ("tri3", (1, 2, 3)),
+ ("tri3", (2, 0, 3)),
+ ("tri3", (0, 2, 1)),
+ ]
+ FACE_MAPPING["tet10"] = [
+ ("tri6", (0, 1, 3, 4, 8, 7)),
+ ("tri6", (1, 2, 3, 5, 9, 8)),
+ ("tri6", (2, 0, 3, 6, 7, 9)),
+ ("tri6", (0, 2, 1, 6, 5, 4)),
+ ]
+ FACE_MAPPING["wedge6"] = [
+ ("quad4", (0, 1, 4, 3)),
+ ("quad4", (1, 2, 5, 4)),
+ ("quad4", (2, 0, 3, 5)),
+ ("tri3", (0, 2, 1)),
+ ("tri3", (3, 4, 5)),
+ ]
+ FACE_MAPPING["wedge12"] = [
+ ("quad6", (0, 1, 4, 3, 6, 9)),
+ ("quad6", (1, 2, 5, 4, 7, 10)),
+ ("quad6", (2, 0, 3, 5, 8, 11)),
+ ("tri6", (0, 2, 1, 8, 7, 6)),
+ ("tri6", (3, 4, 5, 11, 10, 9)),
+ ]
+ FACE_MAPPING["wedge15"] = [
+ ("quad8", (0, 1, 4, 3, 6, 10, 12, 9)),
+ ("quad8", (1, 2, 5, 4, 7, 11, 13, 10)),
+ ("quad8", (2, 0, 3, 5, 8, 9, 14, 11)),
+ ("tri6", (0, 2, 1, 8, 7, 6)),
+ ("tri6", (3, 4, 5, 12, 13, 14)),
+ ]
+ FACE_MAPPING["wedge16"] = FACE_MAPPING["wedge15"]
+ FACE_MAPPING["tri3"] = [("line2", (0, 1)), ("line2", (1, 2)), ("line2", (2, 0))]
+ FACE_MAPPING["tri6"] = [
+ ("line3", (0, 1, 3)),
+ ("line3", (1, 2, 4)),
+ ("line3", (2, 0, 5)),
+ ]
+ FACE_MAPPING["quad4"] = [
+ ("line2", (0, 1)),
+ ("line2", (1, 2)),
+ ("line2", (2, 3)),
+ ("line2", (3, 0)),
+ ]
+ FACE_MAPPING["quad6"] = [
+ ("line3", (0, 1, 4)),
+ ("line2", (1, 2)),
+ ("line3", (2, 5, 3)),
+ ("line2", (3, 0)),
+ ]
+ FACE_MAPPING["quad8"] = [
+ ("line3", (0, 1, 4)),
+ ("line3", (1, 2, 5)),
+ ("line3", (2, 3, 6)),
+ ("line3", (3, 0, 7)),
+ ]
+ FACE_MAPPING["line2"] = [("point", tuple([0])), ("point", tuple([1]))]
+ FACE_MAPPING["line3"] = FACE_MAPPING["line2"]
+ FACE_MAPPING["point"] = []
# define all standard element types
STANDARD_ELEMENT_TYPES = set(FACE_MAPPING.keys())
@@ -267,154 +308,291 @@ Source code for exomerge
# for 2d elements, this flips the element normal
# for 1d elements, this changes the direction
INVERTED_CONNECTIVITY = dict()
- INVERTED_CONNECTIVITY['hex8'] = (4, 5, 6, 7, 0, 1, 2, 3)
- INVERTED_CONNECTIVITY['hex20'] = (4, 5, 6, 7, 0, 1, 2, 3, 16, 17, 18, 19,
- 8, 9, 10, 11, 12, 13, 14, 15)
- INVERTED_CONNECTIVITY['tet4'] = (0, 2, 1, 3)
- INVERTED_CONNECTIVITY['tet10'] = (0, 2, 1, 3, 6, 5, 4, 7, 9, 8)
- INVERTED_CONNECTIVITY['wedge6'] = (3, 4, 5, 0, 1, 2)
- INVERTED_CONNECTIVITY['wedge12'] = (3, 4, 5, 0, 1, 2, 9, 10, 11, 6, 7, 8)
- INVERTED_CONNECTIVITY['wedge15'] = (3, 4, 5, 0, 1, 2, 12, 13, 14, 6, 7, 8,
- 9, 10, 11)
- INVERTED_CONNECTIVITY['wedge16'] = (3, 4, 5, 0, 1, 2, 12, 13, 14, 6, 7, 8,
- 9, 10, 11, 15)
- INVERTED_CONNECTIVITY['tri3'] = (0, 2, 1)
- INVERTED_CONNECTIVITY['tri6'] = (0, 2, 1, 5, 4, 3)
- INVERTED_CONNECTIVITY['quad4'] = (0, 3, 2, 1)
- INVERTED_CONNECTIVITY['quad6'] = (3, 2, 1, 0, 5, 4)
- INVERTED_CONNECTIVITY['quad8'] = (0, 3, 2, 1, 7, 6, 5, 4)
- INVERTED_CONNECTIVITY['line2'] = (1, 0)
- INVERTED_CONNECTIVITY['line3'] = (1, 0, 2)
- INVERTED_CONNECTIVITY['point'] = tuple([0])
+ INVERTED_CONNECTIVITY["hex8"] = (4, 5, 6, 7, 0, 1, 2, 3)
+ INVERTED_CONNECTIVITY["hex20"] = (
+ 4,
+ 5,
+ 6,
+ 7,
+ 0,
+ 1,
+ 2,
+ 3,
+ 16,
+ 17,
+ 18,
+ 19,
+ 8,
+ 9,
+ 10,
+ 11,
+ 12,
+ 13,
+ 14,
+ 15,
+ )
+ INVERTED_CONNECTIVITY["tet4"] = (0, 2, 1, 3)
+ INVERTED_CONNECTIVITY["tet10"] = (0, 2, 1, 3, 6, 5, 4, 7, 9, 8)
+ INVERTED_CONNECTIVITY["wedge6"] = (3, 4, 5, 0, 1, 2)
+ INVERTED_CONNECTIVITY["wedge12"] = (3, 4, 5, 0, 1, 2, 9, 10, 11, 6, 7, 8)
+ INVERTED_CONNECTIVITY["wedge15"] = (
+ 3,
+ 4,
+ 5,
+ 0,
+ 1,
+ 2,
+ 12,
+ 13,
+ 14,
+ 6,
+ 7,
+ 8,
+ 9,
+ 10,
+ 11,
+ )
+ INVERTED_CONNECTIVITY["wedge16"] = (
+ 3,
+ 4,
+ 5,
+ 0,
+ 1,
+ 2,
+ 12,
+ 13,
+ 14,
+ 6,
+ 7,
+ 8,
+ 9,
+ 10,
+ 11,
+ 15,
+ )
+ INVERTED_CONNECTIVITY["tri3"] = (0, 2, 1)
+ INVERTED_CONNECTIVITY["tri6"] = (0, 2, 1, 5, 4, 3)
+ INVERTED_CONNECTIVITY["quad4"] = (0, 3, 2, 1)
+ INVERTED_CONNECTIVITY["quad6"] = (3, 2, 1, 0, 5, 4)
+ INVERTED_CONNECTIVITY["quad8"] = (0, 3, 2, 1, 7, 6, 5, 4)
+ INVERTED_CONNECTIVITY["line2"] = (1, 0)
+ INVERTED_CONNECTIVITY["line3"] = (1, 0, 2)
+ INVERTED_CONNECTIVITY["point"] = tuple([0])
# define a connectivity permutation which rotates the given 2d face
ROTATED_CONNECTIVITY = dict()
- ROTATED_CONNECTIVITY['quad4'] = (3, 0, 1, 2)
- ROTATED_CONNECTIVITY['quad8'] = (3, 0, 1, 2, 7, 4, 5, 6)
- ROTATED_CONNECTIVITY['tri3'] = (2, 0, 1)
- ROTATED_CONNECTIVITY['tri6'] = (2, 0, 1, 5, 3, 4)
+ ROTATED_CONNECTIVITY["quad4"] = (3, 0, 1, 2)
+ ROTATED_CONNECTIVITY["quad8"] = (3, 0, 1, 2, 7, 4, 5, 6)
+ ROTATED_CONNECTIVITY["tri3"] = (2, 0, 1)
+ ROTATED_CONNECTIVITY["tri6"] = (2, 0, 1, 5, 3, 4)
# define the topological dimension of each element
DIMENSION = dict()
- DIMENSION['point'] = 0
- DIMENSION['line2'] = 1
- DIMENSION['line3'] = 1
- DIMENSION['tri3'] = 2
- DIMENSION['tri6'] = 2
- DIMENSION['quad4'] = 2
- DIMENSION['quad6'] = 2
- DIMENSION['quad8'] = 2
- DIMENSION['hex8'] = 3
- DIMENSION['hex20'] = 3
- DIMENSION['tet4'] = 3
- DIMENSION['tet10'] = 3
- DIMENSION['wedge6'] = 3
- DIMENSION['wedge12'] = 3
- DIMENSION['wedge15'] = 3
- DIMENSION['wedge16'] = 3
+ DIMENSION["point"] = 0
+ DIMENSION["line2"] = 1
+ DIMENSION["line3"] = 1
+ DIMENSION["tri3"] = 2
+ DIMENSION["tri6"] = 2
+ DIMENSION["quad4"] = 2
+ DIMENSION["quad6"] = 2
+ DIMENSION["quad8"] = 2
+ DIMENSION["hex8"] = 3
+ DIMENSION["hex20"] = 3
+ DIMENSION["tet4"] = 3
+ DIMENSION["tet10"] = 3
+ DIMENSION["wedge6"] = 3
+ DIMENSION["wedge12"] = 3
+ DIMENSION["wedge15"] = 3
+ DIMENSION["wedge16"] = 3
# define the number of nodes per element
NODES_PER_ELEMENT = dict(
- (key, len(value))
- for key, value in list(INVERTED_CONNECTIVITY.items()))
+ (key, len(value)) for key, value in list(INVERTED_CONNECTIVITY.items())
+ )
# define how to triangulate faces of 3D elements
TRIANGULATED_FACES = dict()
- TRIANGULATED_FACES['tri3'] = [(0, 1, 2)]
- TRIANGULATED_FACES['tri6'] = [(0, 3, 5), (1, 4, 3), (2, 5, 4), (3, 4, 5)]
- TRIANGULATED_FACES['quad4'] = [(0, 1, (0, 1, 2, 3)), (1, 2, (0, 1, 2, 3)),
- (2, 3, (0, 1, 2, 3)), (3, 0, (0, 1, 2, 3))]
- TRIANGULATED_FACES['quad6'] = [(0, 4, (4, 5)), (4, 1, (4, 5)),
- (1, 2, (4, 5)), (2, 5, (4, 5)),
- (5, 3, (4, 5)), (3, 0, (4, 5))]
- TRIANGULATED_FACES['quad8'] = [(4, 7, 0), (5, 4, 1), (6, 5, 2), (7, 6, 3),
- (7, 4, (4, 5, 6, 7)), (4, 5, (4, 5, 6, 7)),
- (5, 6, (4, 5, 6, 7)), (6, 7, (4, 5, 6, 7))]
+ TRIANGULATED_FACES["tri3"] = [(0, 1, 2)]
+ TRIANGULATED_FACES["tri6"] = [(0, 3, 5), (1, 4, 3), (2, 5, 4), (3, 4, 5)]
+ TRIANGULATED_FACES["quad4"] = [
+ (0, 1, (0, 1, 2, 3)),
+ (1, 2, (0, 1, 2, 3)),
+ (2, 3, (0, 1, 2, 3)),
+ (3, 0, (0, 1, 2, 3)),
+ ]
+ TRIANGULATED_FACES["quad6"] = [
+ (0, 4, (4, 5)),
+ (4, 1, (4, 5)),
+ (1, 2, (4, 5)),
+ (2, 5, (4, 5)),
+ (5, 3, (4, 5)),
+ (3, 0, (4, 5)),
+ ]
+ TRIANGULATED_FACES["quad8"] = [
+ (4, 7, 0),
+ (5, 4, 1),
+ (6, 5, 2),
+ (7, 6, 3),
+ (7, 4, (4, 5, 6, 7)),
+ (4, 5, (4, 5, 6, 7)),
+ (5, 6, (4, 5, 6, 7)),
+ (6, 7, (4, 5, 6, 7)),
+ ]
# define formulas for converting between element types
ELEMENT_CONVERSIONS = dict()
- ELEMENT_CONVERSIONS['hex8'] = dict()
- ELEMENT_CONVERSIONS['hex8']['hex20'] = [[
- 0, 1, 2, 3, 4, 5, 6, 7, (0, 1), (1, 2), (2, 3), (0, 3), (0, 4), (1, 5),
- (2, 6), (3, 7), (4, 5), (5, 6), (6, 7), (4, 7)
- ]]
- ELEMENT_CONVERSIONS['hex20'] = dict()
- ELEMENT_CONVERSIONS['hex20']['hex8'] = [list(range(8))]
- ELEMENT_CONVERSIONS['tet4'] = dict()
- ELEMENT_CONVERSIONS['tet4']['tet10'] = [[
- 0, 1, 2, 3, (0, 1), (1, 2), (0, 2), (0, 3), (1, 3), (2, 3)
- ]]
- ELEMENT_CONVERSIONS['tet10'] = dict()
- ELEMENT_CONVERSIONS['tet10']['tet4'] = [list(range(4))]
- ELEMENT_CONVERSIONS['wedge6'] = dict()
- ELEMENT_CONVERSIONS['wedge6']['wedge15'] = [[
- 0, 1, 2, 3, 4, 5, (0, 1), (1, 2), (0, 2), (0, 3), (1, 4), (2, 5),
- (3, 4), (4, 5), (3, 5)
- ]]
- ELEMENT_CONVERSIONS['wedge6']['wedge16'] = [[
- 0, 1, 2, 3, 4, 5, (0, 1), (1, 2), (0, 2), (0, 3), (1, 4), (2, 5),
- (3, 4), (4, 5), (3, 5), (0, 1, 2, 3, 4, 5)
- ]]
- ELEMENT_CONVERSIONS['wedge12'] = dict()
- ELEMENT_CONVERSIONS['wedge12']['wedge6'] = [list(range(6))]
- ELEMENT_CONVERSIONS['wedge12']['wedge15'] = [[
- 0, 1, 2, 3, 4, 5, 6, 7, 8, (0, 3), (1, 4), (2, 5), 9, 10, 11
- ]]
- ELEMENT_CONVERSIONS['wedge15'] = dict()
- ELEMENT_CONVERSIONS['wedge15']['wedge6'] = [list(range(6))]
- ELEMENT_CONVERSIONS['wedge15']['wedge16'] = [[
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, (0, 1, 2, 3, 4, 5)
- ]]
- ELEMENT_CONVERSIONS['wedge16'] = dict()
- ELEMENT_CONVERSIONS['wedge16']['wedge6'] = [list(range(6))]
- ELEMENT_CONVERSIONS['wedge16']['wedge15'] = [list(range(15))]
+ ELEMENT_CONVERSIONS["hex8"] = dict()
+ ELEMENT_CONVERSIONS["hex8"]["hex20"] = [
+ [
+ 0,
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ (0, 1),
+ (1, 2),
+ (2, 3),
+ (0, 3),
+ (0, 4),
+ (1, 5),
+ (2, 6),
+ (3, 7),
+ (4, 5),
+ (5, 6),
+ (6, 7),
+ (4, 7),
+ ]
+ ]
+ ELEMENT_CONVERSIONS["hex20"] = dict()
+ ELEMENT_CONVERSIONS["hex20"]["hex8"] = [list(range(8))]
+ ELEMENT_CONVERSIONS["tet4"] = dict()
+ ELEMENT_CONVERSIONS["tet4"]["tet10"] = [
+ [0, 1, 2, 3, (0, 1), (1, 2), (0, 2), (0, 3), (1, 3), (2, 3)]
+ ]
+ ELEMENT_CONVERSIONS["tet10"] = dict()
+ ELEMENT_CONVERSIONS["tet10"]["tet4"] = [list(range(4))]
+ ELEMENT_CONVERSIONS["wedge6"] = dict()
+ ELEMENT_CONVERSIONS["wedge6"]["wedge15"] = [
+ [
+ 0,
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ (0, 1),
+ (1, 2),
+ (0, 2),
+ (0, 3),
+ (1, 4),
+ (2, 5),
+ (3, 4),
+ (4, 5),
+ (3, 5),
+ ]
+ ]
+ ELEMENT_CONVERSIONS["wedge6"]["wedge16"] = [
+ [
+ 0,
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ (0, 1),
+ (1, 2),
+ (0, 2),
+ (0, 3),
+ (1, 4),
+ (2, 5),
+ (3, 4),
+ (4, 5),
+ (3, 5),
+ (0, 1, 2, 3, 4, 5),
+ ]
+ ]
+ ELEMENT_CONVERSIONS["wedge12"] = dict()
+ ELEMENT_CONVERSIONS["wedge12"]["wedge6"] = [list(range(6))]
+ ELEMENT_CONVERSIONS["wedge12"]["wedge15"] = [
+ [0, 1, 2, 3, 4, 5, 6, 7, 8, (0, 3), (1, 4), (2, 5), 9, 10, 11]
+ ]
+ ELEMENT_CONVERSIONS["wedge15"] = dict()
+ ELEMENT_CONVERSIONS["wedge15"]["wedge6"] = [list(range(6))]
+ ELEMENT_CONVERSIONS["wedge15"]["wedge16"] = [
+ [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, (0, 1, 2, 3, 4, 5)]
+ ]
+ ELEMENT_CONVERSIONS["wedge16"] = dict()
+ ELEMENT_CONVERSIONS["wedge16"]["wedge6"] = [list(range(6))]
+ ELEMENT_CONVERSIONS["wedge16"]["wedge15"] = [list(range(15))]
# define the order of each element
ELEMENT_ORDER = dict()
- ELEMENT_ORDER['hex8'] = 1
- ELEMENT_ORDER['hex20'] = 2
- ELEMENT_ORDER['tet4'] = 1
- ELEMENT_ORDER['tet10'] = 2
- ELEMENT_ORDER['wedge6'] = 1
- ELEMENT_ORDER['wedge12'] = 1
- ELEMENT_ORDER['wedge15'] = 2
- ELEMENT_ORDER['wedge16'] = 2
- ELEMENT_ORDER['tri3'] = 1
- ELEMENT_ORDER['tri6'] = 2
- ELEMENT_ORDER['quad4'] = 1
- ELEMENT_ORDER['quad6'] = 1
- ELEMENT_ORDER['quad8'] = 2
- ELEMENT_ORDER['line2'] = 1
- ELEMENT_ORDER['line3'] = 2
- ELEMENT_ORDER['point'] = 1
+ ELEMENT_ORDER["hex8"] = 1
+ ELEMENT_ORDER["hex20"] = 2
+ ELEMENT_ORDER["tet4"] = 1
+ ELEMENT_ORDER["tet10"] = 2
+ ELEMENT_ORDER["wedge6"] = 1
+ ELEMENT_ORDER["wedge12"] = 1
+ ELEMENT_ORDER["wedge15"] = 2
+ ELEMENT_ORDER["wedge16"] = 2
+ ELEMENT_ORDER["tri3"] = 1
+ ELEMENT_ORDER["tri6"] = 2
+ ELEMENT_ORDER["quad4"] = 1
+ ELEMENT_ORDER["quad6"] = 1
+ ELEMENT_ORDER["quad8"] = 2
+ ELEMENT_ORDER["line2"] = 1
+ ELEMENT_ORDER["line3"] = 2
+ ELEMENT_ORDER["point"] = 1
# define components of multi-component fields
MULTI_COMPONENT_FIELD_SUBSCRIPTS = dict()
- MULTI_COMPONENT_FIELD_SUBSCRIPTS['vector'] = ('x', 'y', 'z')
- MULTI_COMPONENT_FIELD_SUBSCRIPTS['symmetric_3x3_tensor'] = ('xx', 'yy',
- 'zz', 'xy',
- 'yz', 'zx')
- MULTI_COMPONENT_FIELD_SUBSCRIPTS['full_3x3_tensor'] = ('xx', 'yy', 'zz',
- 'xy', 'yz', 'zx',
- 'yx', 'zy', 'xz')
+ MULTI_COMPONENT_FIELD_SUBSCRIPTS["vector"] = ("x", "y", "z")
+ MULTI_COMPONENT_FIELD_SUBSCRIPTS["symmetric_3x3_tensor"] = (
+ "xx",
+ "yy",
+ "zz",
+ "xy",
+ "yz",
+ "zx",
+ )
+ MULTI_COMPONENT_FIELD_SUBSCRIPTS["full_3x3_tensor"] = (
+ "xx",
+ "yy",
+ "zz",
+ "xy",
+ "yz",
+ "zx",
+ "yx",
+ "zy",
+ "xz",
+ )
ALL_MULTI_COMPONENT_FIELD_SUBSCRIPTS = set(
- itertools.chain(*list(MULTI_COMPONENT_FIELD_SUBSCRIPTS.values())))
+ itertools.chain(*list(MULTI_COMPONENT_FIELD_SUBSCRIPTS.values()))
+ )
def __init__(self):
"""Initialize the model."""
# (only) the first time this module is used, show an info banner
global SHOW_BANNER
if SHOW_BANNER:
- print(('\n\nYou are using Exomerge v%s -- A lightweight Python '
- 'interface for manipulating\nExodusII files. (Python-3 version)' % (VERSION)))
+ print(
+ (
+ "\n\nYou are using Exomerge v%s -- A lightweight Python "
+ "interface for manipulating\nExodusII files. (Python-3 version)"
+ % (VERSION)
+ )
+ )
# print out the exodus banner after formatting it to fit within
# 79 characters
exodus_text = exodus.EXODUS_PY_COPYRIGHT
- exodus_text = exodus_text.strip().replace('\n', ' ')
- exodus_text = exodus_text.replace('. ', '. ')
- exodus_text = exodus_text.replace('. ', '. ')
+ exodus_text = exodus_text.strip().replace("\n", " ")
+ exodus_text = exodus_text.replace(". ", ". ")
+ exodus_text = exodus_text.replace(". ", ". ")
exodus_text = textwrap.fill(exodus_text, width=79)
- print(('\n%s\n' % exodus_text))
+ print(("\n%s\n" % exodus_text))
SHOW_BANNER = False
# list of [x, y, z] coordinates for each node
self.nodes = []
@@ -464,28 +642,27 @@ Source code for exomerge
"""
# for special methods, use default behavior
- if name[:2] == '__':
+ if name[:2] == "__":
raise AttributeError
# get non-special function names
- names = [x for x in dir(self.__class__) if x[:2] != '__']
+ names = [x for x in dir(self.__class__) if x[:2] != "__"]
# if the name appears to be singular, search for the plural version
- if not name.endswith('s'):
- trial = name + 's'
+ if not name.endswith("s"):
+ trial = name + "s"
if trial in names:
return getattr(self, trial)
# if the name appears to be plural, search for the singular version
- if name.endswith('s'):
+ if name.endswith("s"):
trial = name[:-1]
- if not trial.endswith('s') and trial in names:
+ if not trial.endswith("s") and trial in names:
return getattr(self, trial)
# we can't find the name, so find names close to it to offer as
# suggestions
# filter names by closeness
- names = dict(
- (x, difflib.SequenceMatcher(None, x, name).ratio()) for x in names)
- sorted_names = sorted(iter(names.items()),
- key=operator.itemgetter(1),
- reverse=True)
+ names = dict((x, difflib.SequenceMatcher(None, x, name).ratio()) for x in names)
+ sorted_names = sorted(
+ iter(names.items()), key=operator.itemgetter(1), reverse=True
+ )
# get the closest 5 matching function names
closest_names = [x[0] for x in sorted_names[0:5]]
# in an interactive shell, just issue a warning, else
@@ -495,16 +672,18 @@ Source code for exomerge
else:
call = self._error
call(
- 'Function not found.',
+ "Function not found.",
'The function "%s" does not exist. Perhaps you meant to '
- 'call one of the following functions:\n\n%s' %
- (name, '\n'.join(closest_names)))
+ "call one of the following functions:\n\n%s"
+ % (name, "\n".join(closest_names)),
+ )
@staticmethod
def _is_interactive():
"""Return True if we're in an interactive shell."""
import __main__ as main
- return not hasattr(main, '__file__')
+
+ return not hasattr(main, "__file__")
@staticmethod
def _assert(condition):
@@ -535,22 +714,38 @@ Source code for exomerge
assert x1 <= x <= x2
values = []
# proportion of y0
- values.append(((x - x1) * (x - x2)**2) / ((x0 - x2) * (x1 - x2)**2))
+ values.append(((x - x1) * (x - x2) ** 2) / ((x0 - x2) * (x1 - x2) ** 2))
# proportion of y1
- values.append(-(((x - x2) *
- (-(x * x1 * (x1 + 3 * x2)) - x1 *
- (x1**2 - 4 * x1 * x2 + x2**2) + x**2 *
- (x1 + x2 - 2 * x3) + x2 * (-3 * x1 + x2) * x3 + x *
- (3 * x1 + x2) * x3)) / ((x1 - x2)**3 * (x1 - x3))))
+ values.append(
+ -(
+ (
+ (x - x2)
+ * (
+ -(x * x1 * (x1 + 3 * x2))
+ - x1 * (x1**2 - 4 * x1 * x2 + x2**2)
+ + x**2 * (x1 + x2 - 2 * x3)
+ + x2 * (-3 * x1 + x2) * x3
+ + x * (3 * x1 + x2) * x3
+ )
+ )
+ / ((x1 - x2) ** 3 * (x1 - x3))
+ )
+ )
# proportion of y2
values.append(
- ((x - x1) *
- (x0 * x1 * (x1 - 3 * x2) + x**2 * (-2 * x0 + x1 + x2) - x2 *
- (x1**2 - 4 * x1 * x2 + x2**2) + x *
- (-(x2 * (3 * x1 + x2)) + x0 * (x1 + 3 * x2)))) / ((x0 - x2) *
- (-x1 + x2)**3))
+ (
+ (x - x1)
+ * (
+ x0 * x1 * (x1 - 3 * x2)
+ + x**2 * (-2 * x0 + x1 + x2)
+ - x2 * (x1**2 - 4 * x1 * x2 + x2**2)
+ + x * (-(x2 * (3 * x1 + x2)) + x0 * (x1 + 3 * x2))
+ )
+ )
+ / ((x0 - x2) * (-x1 + x2) ** 3)
+ )
# proportion of y3
- values.append(((x - x1)**2 * (x - x2)) / ((x1 - x2)**2 * (x3 - x1)))
+ values.append(((x - x1) ** 2 * (x - x2)) / ((x1 - x2) ** 2 * (x3 - x1)))
return values
def _new_element_block_id(self):
@@ -584,10 +779,10 @@ Source code for exomerge
id_ = 1
names = []
for _ in range(quantity):
- name = 'temp%d' % id_
+ name = "temp%d" % id_
while name in self.get_element_field_names():
id_ += 1
- name = 'temp%d' % id_
+ name = "temp%d" % id_
names.append(name)
id_ += 1
if quantity == 1:
@@ -597,28 +792,28 @@ Source code for exomerge
def _new_node_field_name(self):
"""Return a node field name which is not used in the model."""
id_ = 1
- name = 'temp%d' % id_
+ name = "temp%d" % id_
while name in self.get_node_field_names():
id_ += 1
- name = 'temp%d' % id_
+ name = "temp%d" % id_
return name
def _new_side_set_field_name(self):
"""Return a side set field name which is not used in the model."""
id_ = 1
- name = 'temp%d' % id_
+ name = "temp%d" % id_
while name in self.get_side_set_field_names():
id_ += 1
- name = 'temp%d' % id_
+ name = "temp%d" % id_
return name
def _new_node_set_field_name(self):
"""Return a node set field name which is not used in the model."""
id_ = 1
- name = 'temp%d' % id_
+ name = "temp%d" % id_
while name in self.get_node_set_field_names():
id_ += 1
- name = 'temp%d' % id_
+ name = "temp%d" % id_
return name
def _delete_elements(self, element_block_id, element_indices):
@@ -634,7 +829,8 @@ Source code for exomerge
"""
# validate input
[element_block_id] = self._format_element_block_id_list(
- [element_block_id], single=True)
+ [element_block_id], single=True
+ )
self._input_check(element_indices, [list, 0, int])
# get element block information
element_count = self.get_element_count(element_block_id)
@@ -645,11 +841,11 @@ Source code for exomerge
max_element_index = max(element_indices)
if max_element_index >= element_count:
self._error(
- 'Invalid element indices',
- 'The element index list contains invalid entries. '
- 'There are only %d elements in this element block and '
- 'the list contains a reference to index %d.' %
- (max_element_index))
+ "Invalid element indices",
+ "The element index list contains invalid entries. "
+ "There are only %d elements in this element block and "
+ "the list contains a reference to index %d." % (max_element_index),
+ )
# select valid elements
indices_to_delete = set()
invalid_indices = []
@@ -665,19 +861,20 @@ Source code for exomerge
# warn about duplicate indices
if duplicate_indices:
self._warning(
- 'Duplicate element indices',
- 'The element index list contains duplicate '
- 'indices. Elements can only be deleted once so '
- 'duplicates will be ignored. There were %d '
- 'duplicates.' % (len(duplicate_indices)))
+ "Duplicate element indices",
+ "The element index list contains duplicate "
+ "indices. Elements can only be deleted once so "
+ "duplicates will be ignored. There were %d "
+ "duplicates." % (len(duplicate_indices)),
+ )
del duplicate_indices
# error if invalid indices encountered
if invalid_indices:
self._error(
- 'Invalid element indices',
- 'The element index list contains invalid entries. '
- 'There were a total of %d invalid indices.' %
- len(invalid_indices))
+ "Invalid element indices",
+ "The element index list contains invalid entries. "
+ "There were a total of %d invalid indices." % len(invalid_indices),
+ )
del invalid_indices
# create list of nodes used by elements to delete
nodes_per_element = self.get_nodes_per_element(element_block_id)
@@ -685,16 +882,20 @@ Source code for exomerge
used_nodes = []
for element_index in indices_to_delete:
used_nodes.extend(
- connectivity[element_index *
- nodes_per_element:(element_index + 1) *
- nodes_per_element])
+ connectivity[
+ element_index
+ * nodes_per_element: (element_index + 1)
+ * nodes_per_element
+ ]
+ )
used_nodes = set(used_nodes)
# remove references to these elements within each side set
for id_ in self.get_side_set_ids():
# look for members to delete
members = self.get_side_set_members(id_)
members_to_delete = [
- x for x in members
+ x
+ for x in members
if (x[0] == element_block_id and x[1] in indices_to_delete)
]
# delete those members (if any exist)
@@ -702,8 +903,7 @@ Source code for exomerge
self._delete_side_set_members(id_, members_to_delete)
# create translation list
element_count = self.get_element_count(element_block_id)
- remaining_indices = sorted(
- set(range(element_count)) - set(indices_to_delete))
+ remaining_indices = sorted(set(range(element_count)) - set(indices_to_delete))
# create element map
# old element i is new element new_index[i]
new_index = [False] * element_count
@@ -713,15 +913,19 @@ Source code for exomerge
del indices_to_delete
fields = self._get_element_block_fields(element_block_id)
for this_field in list(fields.values()):
- this_field[:] = [[values[x] for x in remaining_indices]
- for values in this_field]
+ this_field[:] = [
+ [values[x] for x in remaining_indices] for values in this_field
+ ]
# delete elements from the block
new_connectivity = []
for element_index in remaining_indices:
new_connectivity.extend(
- connectivity[element_index *
- nodes_per_element:(element_index + 1) *
- nodes_per_element])
+ connectivity[
+ element_index
+ * nodes_per_element: (element_index + 1)
+ * nodes_per_element
+ ]
+ )
# set the new connectivity
self.get_connectivity(element_block_id)[:] = new_connectivity
# set the number of elements
@@ -732,8 +936,7 @@ Source code for exomerge
new_members = []
for member in members:
if member[0] == element_block_id:
- new_members.append(
- (member[0], new_index[member[1]], member[2]))
+ new_members.append((member[0], new_index[member[1]], member[2]))
else:
new_members.append(member)
members[:] = new_members
@@ -745,11 +948,13 @@ Source code for exomerge
# delete those nodes
self._delete_nodes(nodes_to_delete)
-[docs] def threshold_element_blocks(self,
- expression,
- element_block_ids='all',
- timestep='last',
- new_element_block_id=None):
+[docs] def threshold_element_blocks(
+ self,
+ expression,
+ element_block_ids="all",
+ timestep="last",
+ new_element_block_id=None,
+ ):
"""
Delete elements which do not satisfy a condition.
@@ -763,51 +968,50 @@ Source code for exomerge
>>> model.threshold_element_block('all', 'eqps >= 0.01')
"""
- element_block_ids = self._format_element_block_id_list(
- element_block_ids)
- [timestep] = self._format_id_list([timestep],
- self.get_timesteps(),
- 'timestep',
- single=True)
+ element_block_ids = self._format_element_block_id_list(element_block_ids)
+ [timestep] = self._format_id_list(
+ [timestep], self.get_timesteps(), "timestep", single=True
+ )
if new_element_block_id is not None:
if self.element_block_exists(new_element_block_id):
- self._exists_error(new_element_block_id, 'element block')
+ self._exists_error(new_element_block_id, "element block")
# create a temporary field name on these elements
name = self._new_element_field_name()
# evaluate the expression
- self.calculate_element_field('%s = %s' % (name, expression),
- element_block_ids=element_block_ids)
+ self.calculate_element_field(
+ "%s = %s" % (name, expression), element_block_ids=element_block_ids
+ )
# go through each element block and delete elements
for id_ in element_block_ids:
- values = self.get_element_field_values(name,
- element_block_id=id_,
- timestep=timestep)
+ values = self.get_element_field_values(
+ name, element_block_id=id_, timestep=timestep
+ )
# if we're saving elements, duplicate the block, and delete the
# ones we're keeping
if new_element_block_id is not None:
indices_to_keep = [i for i, x in enumerate(values) if x]
temporary_element_block_id = self._new_element_block_id()
- self.duplicate_element_block(id_,
- temporary_element_block_id,
- duplicate_nodes=False)
- self._delete_elements(temporary_element_block_id,
- indices_to_keep)
+ self.duplicate_element_block(
+ id_, temporary_element_block_id, duplicate_nodes=False
+ )
+ self._delete_elements(temporary_element_block_id, indices_to_keep)
if temporary_element_block_id != new_element_block_id:
if self.element_block_exists(new_element_block_id):
self.combine_element_blocks(
[temporary_element_block_id, new_element_block_id],
- new_element_block_id)
+ new_element_block_id,
+ )
else:
- self.rename_element_block(temporary_element_block_id,
- new_element_block_id)
+ self.rename_element_block(
+ temporary_element_block_id, new_element_block_id
+ )
# delete elements which don't meet the threshold
indices_to_delete = [i for i, x in enumerate(values) if not x]
self._delete_elements(id_, indices_to_delete)
# delete the temporary element field
self.delete_element_field(name, element_block_ids=element_block_ids)
if new_element_block_id is not None:
- self.delete_element_field(name,
- element_block_ids=new_element_block_id)
+ self.delete_element_field(name, element_block_ids=new_element_block_id)
def _get_list_ids(self, thing):
"""
@@ -849,8 +1053,7 @@ Source code for exomerge
for values in all_values:
self._assert(len(values) == node_count)
# verify self.element_blocks
- for _, info, connectivity, fields in list(
- self.element_blocks.values()):
+ for _, info, connectivity, fields in list(self.element_blocks.values()):
self._assert(len(info) == 4)
self._assert(len(connectivity) == info[1] * info[2])
if connectivity:
@@ -873,7 +1076,8 @@ Source code for exomerge
# verify self.side_sets
element_count = dict(
(id_, info[1])
- for id_, (_, info, _, _) in list(self.element_blocks.items()))
+ for id_, (_, info, _, _) in list(self.element_blocks.items())
+ )
for _, members, fields in list(self.side_sets.values()):
member_count = len(members)
if members:
@@ -903,26 +1107,26 @@ Source code for exomerge
# get the code line the assertion failed on
_, _, trace = sys.exc_info()
error_line = traceback.extract_tb(trace)[0][3]
- if error_line.startswith('self._assert('):
+ if error_line.startswith("self._assert("):
error_line = error_line[13:-1]
error_line_number = traceback.extract_tb(trace)[0][1]
# write out the error/warning message
self._error(
- 'Corrupted database information.',
- 'The finite element model information failed a validity '
- 'check. The following assertion failed:\n'
- '\n'
- '[%d] %s\n'
- '\n'
- 'This resulted from one of the two scenarios:\n'
- '* You changed information in the database '
- 'inconsistently.\n'
- '* There is a bug within the code.\n'
- '\n'
- 'If you believe it is the latter, please contact support '
- 'with as much information as necessary.\n'
- '* Support contact: %s' %
- (error_line_number, error_line, CONTACT))
+ "Corrupted database information.",
+ "The finite element model information failed a validity "
+ "check. The following assertion failed:\n"
+ "\n"
+ "[%d] %s\n"
+ "\n"
+ "This resulted from one of the two scenarios:\n"
+ "* You changed information in the database "
+ "inconsistently.\n"
+ "* There is a bug within the code.\n"
+ "\n"
+ "If you believe it is the latter, please contact support "
+ "with as much information as necessary.\n"
+ "* Support contact: %s" % (error_line_number, error_line, CONTACT),
+ )
exit(1)
@staticmethod
@@ -951,58 +1155,58 @@ Source code for exomerge
messages = [messages]
for i, message in enumerate(messages):
if not isinstance(message, tuple):
- messages[i] = ('', message)
+ messages[i] = ("", message)
# store the message width
max_header_width = max(len(x[0]) for x in messages)
width = max(width, max_header_width + 20 + 6)
# print the top frame after a blank line
- print('')
- print(('*' * width))
- print(('*' + (' ' * (width - 2)) + '*'))
+ print("")
+ print(("*" * width))
+ print(("*" + (" " * (width - 2)) + "*"))
# process each message
# * Header: Text *
for message in messages:
header = message[0]
# format text into broken lines
- text = ''
- for line in message[1].split('\n'):
+ text = ""
+ for line in message[1].split("\n"):
text += textwrap.fill(line, width=width - 6 - len(header))
- text += '\n'
+ text += "\n"
# remove trailing newlines
- while text and text[-1] == '\n':
+ while text and text[-1] == "\n":
text = text[:-1]
# break into a list
- text = text.split('\n')
+ text = text.split("\n")
# process each line
for i, txt in enumerate(text):
if i == 0:
- line = '%s%s' % (header, txt)
+ line = "%s%s" % (header, txt)
else:
- line = '%s%s' % (' ' * len(header), txt)
+ line = "%s%s" % (" " * len(header), txt)
if len(line) < width - 6:
- line += ' ' * (width - 6 - len(line))
- print(('* %s *' % (line)))
- print(('*' + (' ' * (width - 2)) + '*'))
+ line += " " * (width - 6 - len(line))
+ print(("* %s *" % (line)))
+ print(("*" + (" " * (width - 2)) + "*"))
# print the bottom frame
- print(('*' * width))
+ print(("*" * width))
@staticmethod
def _get_trace(omitted_frames=1):
"""Return a compressed stack trace."""
- last_file = ''
- message = ''
+ last_file = ""
+ message = ""
for frame in inspect.stack()[omitted_frames:]:
- this_file = frame[1].split('/')[-1]
+ this_file = frame[1].split("/")[-1]
if this_file != last_file:
- message += this_file + ':'
+ message += this_file + ":"
last_file = this_file
else:
- message += ' ' * len(last_file) + ' '
- message += frame[3] + ':' + str(frame[2])
- message += '\n'
+ message += " " * len(last_file) + " "
+ message += frame[3] + ":" + str(frame[2])
+ message += "\n"
return message
- def _bug(self, short='Possible bug', detailed='', exit_code=1):
+ def _bug(self, short="Possible bug", detailed="", exit_code=1):
"""
Print out an error message possibly caused by a bug and exit.
@@ -1010,34 +1214,38 @@ Source code for exomerge
information.
"""
- messages = [(' ERROR: ', short)]
+ messages = [(" ERROR: ", short)]
if detailed:
- messages.append(('Message: ', detailed))
+ messages.append(("Message: ", detailed))
messages.append(
- ('Support: ', 'This error may have been caused by a bug in the '
- 'code. If you believe this is the case, please '
- 'contact support and provide enough information '
- 'to duplicate the issue.\n\nSupport contact: %s' % CONTACT))
- messages.append((' Trace: ', self._get_trace()))
+ (
+ "Support: ",
+ "This error may have been caused by a bug in the "
+ "code. If you believe this is the case, please "
+ "contact support and provide enough information "
+ "to duplicate the issue.\n\nSupport contact: %s" % CONTACT,
+ )
+ )
+ messages.append((" Trace: ", self._get_trace()))
self._print_message(messages)
exit(exit_code)
- def _error(self, short='Unspecified error', detailed='', exit_code=1):
+ def _error(self, short="Unspecified error", detailed="", exit_code=1):
"""Print out an error message and exit."""
- messages = [(' ERROR: ', short)]
+ messages = [(" ERROR: ", short)]
if detailed:
- messages.append(('Message: ', detailed))
- messages.append((' Trace: ', self._get_trace()))
+ messages.append(("Message: ", detailed))
+ messages.append((" Trace: ", self._get_trace()))
self._print_message(messages)
exit(exit_code)
- def _warning(self, short='Unspecified warning', detailed=''):
+ def _warning(self, short="Unspecified warning", detailed=""):
"""Print out a warning message, but don't exit."""
- messages = [('WARNING: ', short)]
+ messages = [("WARNING: ", short)]
if detailed:
- messages.append(('Message: ', detailed))
+ messages.append(("Message: ", detailed))
if EXIT_ON_WARNING:
- messages.append((' Trace: ', self._get_trace()))
+ messages.append((" Trace: ", self._get_trace()))
self._print_message(messages)
if EXIT_ON_WARNING:
exit(1)
@@ -1051,23 +1259,21 @@ Source code for exomerge
"""
now = datetime.datetime.today()
- return ('exomerge', VERSION, now.strftime('%Y/%m/%d'),
- now.strftime('%H:%M:%S'))
+ return ("exomerge", VERSION, now.strftime("%Y/%m/%d"), now.strftime("%H:%M:%S"))
- def _ensure_acceptable_id(self, this_id, acceptable_ids, entity=''):
+ def _ensure_acceptable_id(self, this_id, acceptable_ids, entity=""):
"""Ensure ID is acceptable, or error out."""
if this_id not in acceptable_ids:
if entity == "":
self._error("Reference to undefined entity.")
else:
- id_list = string.join([str(x) + ','
- for x in acceptable_ids])[:-1]
+ id_list = string.join([str(x) + "," for x in acceptable_ids])[:-1]
self._error(
"Reference to undefined %s." % (entity),
- "A reference to %s \"%s\" was encountered but is "
- "not defined. There are %d defined %ss: %s" %
- (entity, str(this_id), len(acceptable_ids), entity,
- id_list))
+ 'A reference to %s "%s" was encountered but is '
+ "not defined. There are %d defined %ss: %s"
+ % (entity, str(this_id), len(acceptable_ids), entity, id_list),
+ )
@staticmethod
def _get_matching_strings(string_pattern, list_of_strings):
@@ -1085,8 +1291,8 @@ Source code for exomerge
"""
# convert pattern to a regex expression
- regex_pattern = '^' + string_pattern + '$'
- regex_pattern = regex_pattern.replace('.', r'\.').replace('*', '.*')
+ regex_pattern = "^" + string_pattern + "$"
+ regex_pattern = regex_pattern.replace(".", r"\.").replace("*", ".*")
matches = [x for x in list_of_strings if re.match(regex_pattern, x)]
return matches
@@ -1102,77 +1308,85 @@ Source code for exomerge
bunnies
"""
- if name[-1] == 'y':
- return name[:-1] + 'ies'
- return name + 's'
+ if name[-1] == "y":
+ return name[:-1] + "ies"
+ return name + "s"
def _format_element_block_id_list(self, id_list, *args, **kwargs):
"""Return a validated list of element block IDs."""
blocks = self.element_blocks
- entity = 'element block'
+ entity = "element block"
# get element block translations
- tuples = [(value[0], key) for key, value in list(blocks.items())
- if value[0]]
+ tuples = [(value[0], key) for key, value in list(blocks.items()) if value[0]]
# ensure element block names are unique
if len(set(x[0] for x in tuples)) != len(tuples):
self._warning(
- 'Duplicate %s names' % entity,
- 'At least two %s have the same name. '
- 'This may cause problems.' % self._plural(entity))
- return self._format_id_list(id_list,
- sorted(blocks.keys()),
- entity=entity,
- *args,
- translator=dict(tuples),
- **kwargs)
+ "Duplicate %s names" % entity,
+ "At least two %s have the same name. "
+ "This may cause problems." % self._plural(entity),
+ )
+ return self._format_id_list(
+ id_list,
+ sorted(blocks.keys()),
+ entity=entity,
+ *args,
+ translator=dict(tuples),
+ **kwargs
+ )
def _format_side_set_id_list(self, id_list, *args, **kwargs):
"""Return a validated list of side set IDs."""
ssets = self.side_sets
- entity = 'side set'
+ entity = "side set"
# get element block translations
- tuples = [(value[0], key) for key, value in list(ssets.items())
- if value[0]]
+ tuples = [(value[0], key) for key, value in list(ssets.items()) if value[0]]
# ensure element block names are unique
if len(set(x[0] for x in tuples)) != len(tuples):
self._warning(
- 'Duplicate %s names' % entity,
- 'At least two %s have the same name. '
- 'This may cause problems.' % self._plural(entity))
- return self._format_id_list(id_list,
- sorted(ssets.keys()),
- entity=entity,
- *args,
- translator=dict(tuples),
- **kwargs)
+ "Duplicate %s names" % entity,
+ "At least two %s have the same name. "
+ "This may cause problems." % self._plural(entity),
+ )
+ return self._format_id_list(
+ id_list,
+ sorted(ssets.keys()),
+ entity=entity,
+ *args,
+ translator=dict(tuples),
+ **kwargs
+ )
def _format_node_set_id_list(self, id_list, *args, **kwargs):
"""Return a validated list of node set IDs."""
nsets = self.node_sets
- entity = 'node set'
+ entity = "node set"
# get element block translations
- tuples = [(value[0], key) for key, value in list(nsets.items())
- if value[0]]
+ tuples = [(value[0], key) for key, value in list(nsets.items()) if value[0]]
# ensure element block names are unique
if len(set(x[0] for x in tuples)) != len(tuples):
self._warning(
- 'Duplicate %s names' % entity,
- 'At least two %s have the same name. '
- 'This may cause problems.' % self._plural(entity))
- return self._format_id_list(id_list,
- sorted(nsets.keys()),
- entity=entity,
- *args,
- translator=dict(tuples),
- **kwargs)
-
- def _format_id_list(self,
- id_list,
- acceptable_ids,
- entity='',
- single=False,
- empty_list_okay=True,
- translator={}):
+ "Duplicate %s names" % entity,
+ "At least two %s have the same name. "
+ "This may cause problems." % self._plural(entity),
+ )
+ return self._format_id_list(
+ id_list,
+ sorted(nsets.keys()),
+ entity=entity,
+ *args,
+ translator=dict(tuples),
+ **kwargs
+ )
+
+ def _format_id_list(
+ self,
+ id_list,
+ acceptable_ids,
+ entity="",
+ single=False,
+ empty_list_okay=True,
+ translator={},
+ ):
"""
Return a validated list of IDs.
@@ -1190,37 +1404,39 @@ Source code for exomerge
if not isinstance(id_list, list):
id_list = [id_list]
for id_ in id_list:
- if id_ == 'none':
+ if id_ == "none":
pass
- elif id_ == 'all':
+ elif id_ == "all":
new_id_list.extend(acceptable_ids)
- elif id_ == 'first':
+ elif id_ == "first":
if not acceptable_ids:
self._error(
- 'Empty entity list.',
+ "Empty entity list.",
'The "first" identifier was used to refer to a %s '
- 'but no %ss exist.' % (entity, entity))
+ "but no %ss exist." % (entity, entity),
+ )
new_id_list.append(acceptable_ids[0])
- elif id_ == 'last':
+ elif id_ == "last":
if not acceptable_ids:
self._error(
- 'Empty entity list.',
+ "Empty entity list.",
'The "last" identifier was used to refer to a %s '
- 'but no %ss exist.' % (entity, entity))
+ "but no %ss exist." % (entity, entity),
+ )
new_id_list.append(acceptable_ids[-1])
- elif id_ == 'auto':
+ elif id_ == "auto":
if len(acceptable_ids) != 1:
self._error(
- 'Ambiguous reference.',
+ "Ambiguous reference.",
'The "auto" identifier was used to refer to a %s '
- 'but exactly one %s does not exist. There are %d '
- 'defined %ss.' %
- (entity, entity, len(acceptable_ids), entity))
+ "but exactly one %s does not exist. There are %d "
+ "defined %ss." % (entity, entity, len(acceptable_ids), entity),
+ )
new_id_list.append(acceptable_ids[0])
- elif id_ == 'last_if_any':
+ elif id_ == "last_if_any":
if acceptable_ids:
new_id_list.append(acceptable_ids[-1])
- elif id_ == 'first_if_any':
+ elif id_ == "first_if_any":
if acceptable_ids:
new_id_list.append(acceptable_ids[-1])
else:
@@ -1228,18 +1444,16 @@ Source code for exomerge
id_list = new_id_list
# now apply the translation list
if translator:
- id_list = [
- translator[x] if x in translator else x for x in id_list
- ]
+ id_list = [translator[x] if x in translator else x for x in id_list]
# for ids with a wildcard, find all that match
if id_list and isinstance(id_list[0], str):
for i in reversed(range(len(id_list))):
this_id = id_list[i]
- if '*' in this_id:
+ if "*" in this_id:
del id_list[i]
for new_id in reversed(
- self._get_matching_strings(this_id,
- acceptable_ids)):
+ self._get_matching_strings(this_id, acceptable_ids)
+ ):
id_list.insert(i, new_id)
# do not allow duplicates
# and ensure all given ids are valid
@@ -1251,37 +1465,49 @@ Source code for exomerge
if id_ in acceptable_ids:
unique_ids.append(id_)
else:
- id_list = ', '.join([str(x) for x in acceptable_ids])
+ id_list = ", ".join([str(x) for x in acceptable_ids])
self._warning(
- 'Reference to undefined %s.' % (entity),
- 'A reference to %s \"%s\" was encountered but is '
- 'not defined. This %s will not be included in the '
- 'operation.\n\nThere are %d defined %s: %s' %
- (entity, id_, entity, len(acceptable_ids),
- self._plural(entity), id_list))
+ "Reference to undefined %s." % (entity),
+ 'A reference to %s "%s" was encountered but is '
+ "not defined. This %s will not be included in the "
+ "operation.\n\nThere are %d defined %s: %s"
+ % (
+ entity,
+ id_,
+ entity,
+ len(acceptable_ids),
+ self._plural(entity),
+ id_list,
+ ),
+ )
# return the unique list
id_list = unique_ids
# if only a single item was requested, ensure it exists
if single and len(id_list) != 1:
if not id_list:
self._error(
- 'No %s specified.' % entity,
- 'A single %s is required but none '
- 'were specified.' % entity)
+ "No %s specified." % entity,
+ "A single %s is required but none " "were specified." % entity,
+ )
self._error(
- 'Multiple %ss specified.' % entity,
- 'A single %s is required but %d %ss were specified: %s' %
- (entity, len(id_list), entity, ', '.join(
- [str(x) for x in id_list])))
+ "Multiple %ss specified." % entity,
+ "A single %s is required but %d %ss were specified: %s"
+ % (entity, len(id_list), entity, ", ".join([str(x) for x in id_list])),
+ )
# if list is empty and that's a problem, error out
if not empty_list_okay and not id_list:
self._error(
- 'No %ss specified.' % entity,
- 'We require at least one %s to be specified for this '
- 'opration but none were specified.\n\nThere are %d '
- 'defined %s: %s' %
- (entity, len(acceptable_ids), self._plural(entity), ', '.join(
- [str(x) for x in acceptable_ids])))
+ "No %ss specified." % entity,
+ "We require at least one %s to be specified for this "
+ "opration but none were specified.\n\nThere are %d "
+ "defined %s: %s"
+ % (
+ entity,
+ len(acceptable_ids),
+ self._plural(entity),
+ ", ".join([str(x) for x in acceptable_ids]),
+ ),
+ )
return id_list
def _get_standard_element_type(self, element_type, warning=True):
@@ -1303,43 +1529,44 @@ Source code for exomerge
"""
if isinstance(element_type, bytes):
- element_type = element_type.decode('utf8').lower()
+ element_type = element_type.decode("utf8").lower()
else:
element_type = element_type.lower()
translation_list = {
- 'hex': 'hex8',
- 'tet': 'tet4',
- 'tetra': 'tet4',
- 'tetra10': 'tet10',
- 'tri': 'tri3',
- 'triangle': 'tri3',
- 'quad': 'quad4',
- 'shell4': 'quad4',
- 'wedge': 'wedge6'
+ "hex": "hex8",
+ "tet": "tet4",
+ "tetra": "tet4",
+ "tetra10": "tet10",
+ "tri": "tri3",
+ "triangle": "tri3",
+ "quad": "quad4",
+ "shell4": "quad4",
+ "wedge": "wedge6",
}
if element_type in translation_list:
element_type = translation_list[element_type]
if warning and element_type not in self.STANDARD_ELEMENT_TYPES:
self._warning(
- 'Nonstandard element type',
+ "Nonstandard element type",
'The element type "%s" is not a standard '
- 'element type. This may cause issues with '
- 'handling element blocks with elements of '
- 'this type.' % (element_type))
+ "element type. This may cause issues with "
+ "handling element blocks with elements of "
+ "this type." % (element_type),
+ )
return element_type
def _get_default_field_value(self, name):
"""Return the default value for a field with the given name."""
if self._is_displacement_field_prefix(name[:-2]):
return 0.0
- return float('nan')
+ return float("nan")
@staticmethod
def _is_displacement_field_prefix(name):
"""Return 'True' if name is a displacement field prefix."""
- default_name = 'displacement'
- if len(name) >= 3 and name.lower() == default_name[:len(name)]:
+ default_name = "displacement"
+ if len(name) >= 3 and name.lower() == default_name[: len(name)]:
return True
return False
@@ -1350,10 +1577,10 @@ Source code for exomerge
If no displacement field exists, this will return the default prefix.
"""
- prefix = 'disp'
+ prefix = "disp"
for node_field_name in self.get_node_field_names():
# if it doesn't end in "_x", it's not a prefix
- if len(node_field_name) < 3 or node_field_name[-2] != '_':
+ if len(node_field_name) < 3 or node_field_name[-2] != "_":
continue
# check against acceptable names
this_prefix = node_field_name[:-2]
@@ -1372,7 +1599,8 @@ Source code for exomerge
"""
element_block_ids = self._format_element_block_id_list(
- element_block_ids, empty_list_okay=False)
+ element_block_ids, empty_list_okay=False
+ )
members = []
for id_ in element_block_ids:
mapping = self._get_face_mapping_from_id(id_)
@@ -1384,10 +1612,11 @@ Source code for exomerge
def _get_block_info(self, element_block_id):
"""Return the info of an element block."""
[element_block_id] = self._format_element_block_id_list(
- [element_block_id], single=True)
+ [element_block_id], single=True
+ )
return self.element_blocks[element_block_id][1]
- def _get_external_element_faces(self, element_block_ids='all'):
+ def _get_external_element_faces(self, element_block_ids="all"):
"""
Return a list of external element faces.
@@ -1397,8 +1626,7 @@ Source code for exomerge
* '(element_block_id, element_index, face_index)'
"""
- element_block_ids = self._format_element_block_id_list(
- element_block_ids)
+ element_block_ids = self._format_element_block_id_list(element_block_ids)
external_faces = dict()
for id_ in element_block_ids:
info = self._get_block_info(id_)
@@ -1407,19 +1635,16 @@ Source code for exomerge
for element_index in range(info[1]):
for face_index, (_, face) in enumerate(face_mapping):
sorted_nodes = tuple(
- sorted([
- connectivity[element_index * info[2] + x]
- for x in face
- ]))
+ sorted(
+ [connectivity[element_index * info[2] + x] for x in face]
+ )
+ )
if sorted_nodes in external_faces:
external_faces[sorted_nodes] = None
else:
this_face = (id_, element_index, face_index)
external_faces[sorted_nodes] = this_face
- return [
- value for value in list(external_faces.values())
- if value is not None
- ]
+ return [value for value in list(external_faces.values()) if value is not None]
@staticmethod
def _mean(values):
@@ -1442,8 +1667,7 @@ Source code for exomerge
for element_block_id, element_index, face_index in members:
if element_block_id not in members_by_block:
members_by_block[element_block_id] = []
- members_by_block[element_block_id].append(
- (element_index, face_index))
+ members_by_block[element_block_id].append((element_index, face_index))
return members_by_block
def _get_dimension(self, element_type):
@@ -1456,14 +1680,15 @@ Source code for exomerge
element_type = self._get_standard_element_type(element_type)
if element_type not in self.TRIANGULATED_FACES:
self._bug(
- 'Invalid element type.',
- 'We do not know how to subdivide an element of type '
- '"%s" into triangles.' % element_type)
+ "Invalid element type.",
+ "We do not know how to subdivide an element of type "
+ '"%s" into triangles.' % element_type,
+ )
return self.TRIANGULATED_FACES[element_type]
- def _convert_side_set_to_triangle_block(self,
- side_set_ids,
- new_element_block_id='auto'):
+ def _convert_side_set_to_triangle_block(
+ self, side_set_ids, new_element_block_id="auto"
+ ):
"""
Create a new 'tri3' element block composed of the given side set.
@@ -1471,25 +1696,26 @@ Source code for exomerge
"""
side_set_ids = self._format_side_set_id_list(side_set_ids)
- if new_element_block_id == 'auto':
+ if new_element_block_id == "auto":
new_element_block_id = self._new_element_block_id()
new_nodes = []
# find members of all the given side sets by block
members_by_block = self._order_element_faces_by_block(
- itertools.chain(
- *[self.get_side_set_members(x) for x in side_set_ids]))
+ itertools.chain(*[self.get_side_set_members(x) for x in side_set_ids])
+ )
# ensure all blocks are 3D
for id_ in list(members_by_block.keys()):
element_type = self._get_element_type(id_)
dimension = self._get_dimension(element_type)
if dimension != 3:
self._error(
- 'Incompatible element dimension.',
- 'We expect the side set to contain faces of 3D '
- 'elements. However, the side set contains at '
- 'least one face from element block %d which '
- 'contains %dD elements of type "%s".' %
- (id_, dimension, element_type))
+ "Incompatible element dimension.",
+ "We expect the side set to contain faces of 3D "
+ "elements. However, the side set contains at "
+ "least one face from element block %d which "
+ 'contains %dD elements of type "%s".'
+ % (id_, dimension, element_type),
+ )
# Now we need to create the triangles from each member of the side set.
faces = dict()
for element_block_id, members in list(members_by_block.items()):
@@ -1498,10 +1724,11 @@ Source code for exomerge
face_mapping = self._get_face_mapping_from_id(element_block_id)
for element_index, face_index in members:
face_element_map = face_mapping[face_index]
- local_node = connectivity[element_index *
- nodes_per_element:(element_index +
- 1) *
- nodes_per_element]
+ local_node = connectivity[
+ element_index
+ * nodes_per_element: (element_index + 1)
+ * nodes_per_element
+ ]
local_node = tuple(local_node[x] for x in face_element_map[1])
if face_element_map[0] not in faces:
faces[face_element_map[0]] = [local_node]
@@ -1519,8 +1746,7 @@ Source code for exomerge
if isinstance(index, int):
connectivity.append(local_face_indices[index])
continue
- averaged_nodes = tuple(local_face_indices[x]
- for x in index)
+ averaged_nodes = tuple(local_face_indices[x] for x in index)
if not new_nodes or new_nodes[-1] != averaged_nodes:
new_nodes.append(averaged_nodes)
next_node_index += 1
@@ -1528,9 +1754,9 @@ Source code for exomerge
# create the new nodes
self._create_averaged_nodes(new_nodes, [])
# create the new element block
- self.create_element_block(new_element_block_id,
- ['tri3', len(connectivity) // 3, 3, 0],
- connectivity)
+ self.create_element_block(
+ new_element_block_id, ["tri3", len(connectivity) // 3, 3, 0], connectivity
+ )
@staticmethod
def _sign(x):
@@ -1546,10 +1772,14 @@ Source code for exomerge
return -1
return 0
- def _partition_triangle_block_from_node_field(self, element_block_id,
- new_element_block_id,
- node_field_name, timestep,
- interval_list):
+ def _partition_triangle_block_from_node_field(
+ self,
+ element_block_id,
+ new_element_block_id,
+ node_field_name,
+ timestep,
+ interval_list,
+ ):
"""
Subdivide a 'tri3' element block based on the given field intervals.
@@ -1560,29 +1790,28 @@ Source code for exomerge
"""
[element_block_id] = self._format_element_block_id_list(
- [element_block_id], single=True)
- [node_field_name] = self._format_id_list([node_field_name],
- self.get_node_field_names(),
- 'node field',
- single=True)
- [timestep] = self._format_id_list([timestep],
- self.get_timesteps(),
- 'timestep',
- single=True)
+ [element_block_id], single=True
+ )
+ [node_field_name] = self._format_id_list(
+ [node_field_name], self.get_node_field_names(), "node field", single=True
+ )
+ [timestep] = self._format_id_list(
+ [timestep], self.get_timesteps(), "timestep", single=True
+ )
# verify block is actually a tri3 block
- if self._get_element_type(element_block_id) != 'tri3':
+ if self._get_element_type(element_block_id) != "tri3":
self._error(
- 'Invalid element type',
- 'This function can only be used to divide element '
- 'blocks composed of "tri3" elements.')
+ "Invalid element type",
+ "This function can only be used to divide element "
+ 'blocks composed of "tri3" elements.',
+ )
timestep_index = self.timesteps.index(timestep)
connectivity = self.get_connectivity(element_block_id)
element_count = self.get_element_count(element_block_id)
new_connectivity = []
element_interval_values = []
triangles = [
- tuple(connectivity[x * 3:(x + 1) * 3])
- for x in range(element_count)
+ tuple(connectivity[x * 3: (x + 1) * 3]) for x in range(element_count)
]
for index, upper_bound in enumerate(interval_list):
# hold new vertices we have to create
@@ -1597,15 +1826,19 @@ Source code for exomerge
for d in range(3):
d2 = (d + 1) % 3
edge = (tri[d], tri[d2])
- if (self._sign(values[tri[d]] - upper_bound) *
- self._sign(values[tri[d2]] - upper_bound) == -1):
+ if (
+ self._sign(values[tri[d]] - upper_bound)
+ * self._sign(values[tri[d2]] - upper_bound)
+ == -1
+ ):
if edge not in new_vertex:
opposite_edge = tuple(reversed(edge))
new_vertex[edge] = next_node_index
new_vertex[opposite_edge] = next_node_index
next_node_index += 1
phi = (upper_bound - values[tri[d]]) / (
- values[tri[d2]] - values[tri[d]])
+ values[tri[d2]] - values[tri[d]]
+ )
new_node = ((tri[d], 1.0 - phi), (tri[d2], phi))
new_nodes.append(new_node)
self._create_averaged_nodes(new_nodes, [])
@@ -1614,24 +1847,30 @@ Source code for exomerge
this_partition = []
values = self.node_fields[node_field_name][timestep_index]
for tri in triangles:
- if (values[tri[0]] <= upper_bound
- and values[tri[1]] <= upper_bound
- and values[tri[2]] <= upper_bound):
+ if (
+ values[tri[0]] <= upper_bound
+ and values[tri[1]] <= upper_bound
+ and values[tri[2]] <= upper_bound
+ ):
this_partition.append(tri)
- elif (values[tri[0]] >= upper_bound
- and values[tri[1]] >= upper_bound
- and values[tri[2]] >= upper_bound):
+ elif (
+ values[tri[0]] >= upper_bound
+ and values[tri[1]] >= upper_bound
+ and values[tri[2]] >= upper_bound
+ ):
new_triangles.append(tri)
else:
# find vertex below the bound
d = 0
- while (values[tri[d]] >= upper_bound
- or values[tri[(d + 1) % 3]] < upper_bound):
+ while (
+ values[tri[d]] >= upper_bound
+ or values[tri[(d + 1) % 3]] < upper_bound
+ ):
d += 1
tri = tuple(tri[(d + x) % 3] for x in range(3))
case = tuple(
- self._sign(values[tri[x]] - upper_bound)
- for x in range(3))
+ self._sign(values[tri[x]] - upper_bound) for x in range(3)
+ )
if case == (-1, 1, -1):
m1 = new_vertex[(tri[0], tri[1])]
m2 = new_vertex[(tri[1], tri[2])]
@@ -1661,21 +1900,21 @@ Source code for exomerge
# above triangles
new_triangles.append((m1, tri[1], tri[2]))
else:
- self._bug('Unknown case')
+ self._bug("Unknown case")
triangles = new_triangles
new_connectivity.extend(itertools.chain(*this_partition))
- element_interval_values.extend([float(index)] *
- len(this_partition))
+ element_interval_values.extend([float(index)] * len(this_partition))
# add rest of triangle to last partition
new_connectivity.extend(itertools.chain(*triangles))
- element_interval_values.extend([float(len(interval_list))] *
- len(triangles))
+ element_interval_values.extend([float(len(interval_list))] * len(triangles))
self.create_element_block(
new_element_block_id,
- ['tri3', len(new_connectivity) // 3, 3, 0], new_connectivity)
- self.create_element_field('interval', new_element_block_id, 0.0)
+ ["tri3", len(new_connectivity) // 3, 3, 0],
+ new_connectivity,
+ )
+ self.create_element_field("interval", new_element_block_id, 0.0)
fields = self._get_element_block_fields(new_element_block_id)
- field = fields['interval']
+ field = fields["interval"]
for index in range(len(self.timesteps)):
field[index] = list(element_interval_values)
@@ -1686,33 +1925,36 @@ Source code for exomerge
This includes the displacement if it exists.
"""
- timestep = self._format_id_list(timestep, self.get_timesteps(),
- 'timestep')
+ timestep = self._format_id_list(timestep, self.get_timesteps(), "timestep")
if len(timestep) > 1:
self._error(
- 'Ambiguous timestep.',
- 'More than one timestep was specified. We expected '
- 'one or zero timesteps.')
+ "Ambiguous timestep.",
+ "More than one timestep was specified. We expected "
+ "one or zero timesteps.",
+ )
if not timestep:
return [tuple(x) for x in self.nodes]
timestep_index = self.timesteps.index(timestep[0])
displacement_values = [
x[timestep_index] for x in self._get_displacement_field_values()
]
- return [(x + dx, y + dy, z + dz)
- for (x, y,
- z), dx, dy, dz in zip(self.nodes, *displacement_values)]
-
-[docs] def export_wrl_model(self,
- filename,
- node_field_name,
- element_block_ids='all',
- timestep='last',
- field_range='auto',
- intervals=9,
- colorspace='rgb',
- displacement_timestep='auto',
- export_exodus_copy=True):
+ return [
+ (x + dx, y + dy, z + dz)
+ for (x, y, z), dx, dy, dz in zip(self.nodes, *displacement_values)
+ ]
+
+[docs] def export_wrl_model(
+ self,
+ filename,
+ node_field_name,
+ element_block_ids="all",
+ timestep="last",
+ field_range="auto",
+ intervals=9,
+ colorspace="rgb",
+ displacement_timestep="auto",
+ export_exodus_copy=True,
+ ):
"""
Export the exterior of the model to a colored WRL file.
@@ -1722,31 +1964,25 @@ Source code for exomerge
>>> model.export_wrl_model('colored_eqps_model.wrl', 'eqps')
"""
- element_block_ids = self._format_element_block_id_list(
- element_block_ids)
- [node_field_name] = self._format_id_list([node_field_name],
- self.get_node_field_names(),
- 'node field',
- single=True)
- [timestep] = self._format_id_list([timestep],
- self.get_timesteps(),
- 'timestep',
- single=True)
+ element_block_ids = self._format_element_block_id_list(element_block_ids)
+ [node_field_name] = self._format_id_list(
+ [node_field_name], self.get_node_field_names(), "node field", single=True
+ )
+ [timestep] = self._format_id_list(
+ [timestep], self.get_timesteps(), "timestep", single=True
+ )
timestep_index = self.timesteps.index(timestep)
- if displacement_timestep == 'auto':
+ if displacement_timestep == "auto":
if self.displacement_field_exists():
displacement_timestep = timestep
else:
- displacement_timestep = 'none'
+ displacement_timestep = "none"
else:
[displacement_timestep] = self._format_id_list(
- [displacement_timestep],
- self.get_timesteps(),
- 'timestep',
- single=True)
+ [displacement_timestep], self.get_timesteps(), "timestep", single=True
+ )
# all element blocks should either be 3D elements, or 'tri3' elements
- element_types = set(
- self._get_element_type(x) for x in element_block_ids)
+ element_types = set(self._get_element_type(x) for x in element_block_ids)
element_dimensions = set(self._get_dimension(x) for x in element_types)
# if we have all 3D elements, create a skin
if element_dimensions == set([3]):
@@ -1754,49 +1990,50 @@ Source code for exomerge
external_side_set_id = self._new_side_set_id()
self.create_side_set(
external_side_set_id,
- self._get_external_element_faces(element_block_ids))
+ self._get_external_element_faces(element_block_ids),
+ )
self._convert_side_set_to_triangle_block(
- external_side_set_id, triangle_element_block_id)
+ external_side_set_id, triangle_element_block_id
+ )
self.delete_side_set(external_side_set_id)
- elif element_dimensions == set([2]) and element_types == set(['tri3']):
+ elif element_dimensions == set([2]) and element_types == set(["tri3"]):
# merge all blocks into another block
ids_to_merge = []
for id_ in element_block_ids:
ids_to_merge.append(self._new_element_block_id())
self.duplicate_element_block(id_, ids_to_merge[-1])
triangle_element_block_id = self._new_element_block_id()
- self.combine_element_blocks(ids_to_merge,
- triangle_element_block_id)
+ self.combine_element_blocks(ids_to_merge, triangle_element_block_id)
# these blocks better form a watertight enclosure
- external_sides = self._get_external_element_faces(
- triangle_element_block_id)
+ external_sides = self._get_external_element_faces(triangle_element_block_id)
if external_sides:
self._warning(
- 'Enclosure is not watertight.',
+ "Enclosure is not watertight.",
'The "tri3" element blocks passed to this function do not '
- 'form a watertight enclosure. An output file will still '
- 'be created, but it is unlikely to be useful as a WRL '
- 'model. We found %d unmatched sides.' %
- len(external_sides))
+ "form a watertight enclosure. An output file will still "
+ "be created, but it is unlikely to be useful as a WRL "
+ "model. We found %d unmatched sides." % len(external_sides),
+ )
else:
self._error(
- 'Invalid input.',
- 'We expect a list of 3D element blocks or a list of '
- '2D element blocks composed of triangles.')
+ "Invalid input.",
+ "We expect a list of 3D element blocks or a list of "
+ "2D element blocks composed of triangles.",
+ )
# now that we have a triangle block, subdivide it
subdivided_element_block_id = self._new_element_block_id()
# set up intervals
- if field_range == 'auto':
- indices = self.get_nodes_in_element_block(
- triangle_element_block_id)
+ if field_range == "auto":
+ indices = self.get_nodes_in_element_block(triangle_element_block_id)
values = self.node_fields[node_field_name][timestep_index]
this_values = [values[x] for x in indices]
field_range = [min(this_values), max(this_values)]
if field_range[0] >= field_range[1]:
self._error(
- 'Invalid field range.',
- 'The given field range [%g - %g] was not valid.' %
- (field_range[0], field_range[1]))
+ "Invalid field range.",
+ "The given field range [%g - %g] was not valid."
+ % (field_range[0], field_range[1]),
+ )
if isinstance(intervals, int):
intervals = [
(1 - phi) * field_range[0] + phi * field_range[1]
@@ -1804,87 +2041,95 @@ Source code for exomerge
]
# partition that block based on the node field
self._partition_triangle_block_from_node_field(
- triangle_element_block_id, subdivided_element_block_id,
- node_field_name, timestep, intervals)
+ triangle_element_block_id,
+ subdivided_element_block_id,
+ node_field_name,
+ timestep,
+ intervals,
+ )
# save model as an ExodusII file so we can view it
if export_exodus_copy:
temp_nodes = self.nodes
self.nodes = self._get_coordinates_at_time(displacement_timestep)
- exodus_filename = filename.rsplit('.', 1)[0] + '_wrl.e'
- self.export_model(exodus_filename,
- element_block_ids=subdivided_element_block_id,
- element_field_names='interval',
- node_field_names='none',
- node_set_ids='none',
- side_set_ids='none',
- global_variable_names='none',
- timesteps=[timestep])
+ exodus_filename = filename.rsplit(".", 1)[0] + "_wrl.e"
+ self.export_model(
+ exodus_filename,
+ element_block_ids=subdivided_element_block_id,
+ element_field_names="interval",
+ node_field_names="none",
+ node_set_ids="none",
+ side_set_ids="none",
+ global_variable_names="none",
+ timesteps=[timestep],
+ )
self.nodes = temp_nodes
# save triangles to the WRL file
- with open(filename, 'w') as output:
- output.write('#VRML V2.0 utf8\n')
- output.write('Transform {\n')
- output.write(' translation 0.0 0.0 0.0\n')
- output.write(' children Shape {\n')
- output.write(' appearance Appearance {material Material {} }\n')
- output.write(' geometry IndexedFaceSet {\n')
- output.write(' coord Coordinate {\n')
- output.write(' point [\n')
- for position in self._get_coordinates_at_time(
- displacement_timestep):
- output.write(','.join(str(x) for x in position))
- output.write(',')
- output.write('\n ]\n')
- output.write(' }\n')
- output.write(' coordIndex [\n')
+ with open(filename, "w") as output:
+ output.write("#VRML V2.0 utf8\n")
+ output.write("Transform {\n")
+ output.write(" translation 0.0 0.0 0.0\n")
+ output.write(" children Shape {\n")
+ output.write(" appearance Appearance {material Material {} }\n")
+ output.write(" geometry IndexedFaceSet {\n")
+ output.write(" coord Coordinate {\n")
+ output.write(" point [\n")
+ for position in self._get_coordinates_at_time(displacement_timestep):
+ output.write(",".join(str(x) for x in position))
+ output.write(",")
+ output.write("\n ]\n")
+ output.write(" }\n")
+ output.write(" coordIndex [\n")
connectivity = self.get_connectivity(subdivided_element_block_id)
element_count = self.get_element_count(subdivided_element_block_id)
for element_index in range(element_count):
- output.write('%d,%d,%d,-1,' %
- (connectivity[element_index * 3 + 0],
- connectivity[element_index * 3 + 1],
- connectivity[element_index * 3 + 2]))
- output.write('\n ]\n')
- output.write(' color Color {\n')
- output.write(' color [\n')
- if colorspace == 'rgb':
+ output.write(
+ "%d,%d,%d,-1,"
+ % (
+ connectivity[element_index * 3 + 0],
+ connectivity[element_index * 3 + 1],
+ connectivity[element_index * 3 + 2],
+ )
+ )
+ output.write("\n ]\n")
+ output.write(" color Color {\n")
+ output.write(" color [\n")
+ if colorspace == "rgb":
colorspace = [
- colorsys.hls_to_rgb(2.0 / 3 - 2.0 / 3 * x / len(intervals),
- 0.5, 1)
+ colorsys.hls_to_rgb(2.0 / 3 - 2.0 / 3 * x / len(intervals), 0.5, 1)
for x in range(len(intervals) + 1)
]
if len(colorspace) != len(intervals) + 1:
self._error(
- 'Unrecognized colorspace.',
- 'The given colorspace was not recognized. We '
+ "Unrecognized colorspace.",
+ "The given colorspace was not recognized. We "
'expected a string such as "rgb" or a list of '
- 'length %d with RGB triplets. Instead, we found '
- '"%s".' % (len(intervals) + 1, str(colorspace)))
+ "length %d with RGB triplets. Instead, we found "
+ '"%s".' % (len(intervals) + 1, str(colorspace)),
+ )
for color in colorspace:
- output.write(' %s,\n' %
- ' '.join(str(x) for x in color))
- output.write(' ]\n')
- output.write(' }\n')
- output.write(' colorIndex [\n')
- output.write(' ')
+ output.write(" %s,\n" % " ".join(str(x) for x in color))
+ output.write(" ]\n")
+ output.write(" }\n")
+ output.write(" colorIndex [\n")
+ output.write(" ")
values = self.get_element_field_values(
- 'interval', subdivided_element_block_id,
- self.timesteps[timestep_index])
- output.write(','.join(str(int(x)) for x in values))
- output.write('\n')
- output.write(' ]\n')
- output.write(' colorPerVertex FALSE\n')
- output.write(' }\n')
- output.write(' }\n')
- output.write('}\n')
+ "interval", subdivided_element_block_id, self.timesteps[timestep_index]
+ )
+ output.write(",".join(str(int(x)) for x in values))
+ output.write("\n")
+ output.write(" ]\n")
+ output.write(" colorPerVertex FALSE\n")
+ output.write(" }\n")
+ output.write(" }\n")
+ output.write("}\n")
# delete the temporary element blocks
self.delete_element_block(
- [triangle_element_block_id, subdivided_element_block_id])
+ [triangle_element_block_id, subdivided_element_block_id]
+ )
-[docs] def export_stl_file(self,
- filename,
- element_block_ids='all',
- displacement_timestep='auto'):
+[docs] def export_stl_file(
+ self, filename, element_block_ids="all", displacement_timestep="auto"
+ ):
"""
Export the exterior of the model to an STL file.
@@ -1895,47 +2140,46 @@ Source code for exomerge
>>> model.export_stl_file('mesh_surface.stl')
"""
- element_block_ids = self._format_element_block_id_list(
- element_block_ids)
- if displacement_timestep == 'auto':
+ element_block_ids = self._format_element_block_id_list(element_block_ids)
+ if displacement_timestep == "auto":
if self.timesteps and self.displacement_field_exists():
- displacement_timestep = 'last'
+ displacement_timestep = "last"
else:
- displacement_timestep = 'none'
+ displacement_timestep = "none"
# create a new element block composed of triangles
triangle_element_block_id = self._new_element_block_id()
external_side_set_id = self._new_side_set_id()
self.create_side_set(
- external_side_set_id,
- self._get_external_element_faces(element_block_ids))
- self._convert_side_set_to_triangle_block(external_side_set_id,
- triangle_element_block_id)
+ external_side_set_id, self._get_external_element_faces(element_block_ids)
+ )
+ self._convert_side_set_to_triangle_block(
+ external_side_set_id, triangle_element_block_id
+ )
# export that set
- displacement_timestep = self._format_id_list(displacement_timestep,
- self.get_timesteps(),
- 'timestep')
+ displacement_timestep = self._format_id_list(
+ displacement_timestep, self.get_timesteps(), "timestep"
+ )
# get coordinates at the time we care about
c = self._get_coordinates_at_time(displacement_timestep)
# create the STL file
connectivity = self.get_connectivity(triangle_element_block_id)
- with open(filename, 'wb') as output:
- output.write(b' ' * 80)
- output.write(struct.pack('<l', len(connectivity) // 3))
+ with open(filename, "wb") as output:
+ output.write(b" " * 80)
+ output.write(struct.pack("<l", len(connectivity) // 3))
for element_index in range(len(connectivity) // 3):
- tri = connectivity[element_index * 3:(element_index + 1) * 3]
- normal = (c[tri[1]][1] * c[tri[2]][2] -
- c[tri[2]][1] * c[tri[1]][2],
- c[tri[1]][2] * c[tri[2]][0] -
- c[tri[2]][2] * c[tri[1]][0],
- c[tri[1]][0] * c[tri[2]][1] -
- c[tri[2]][0] * c[tri[1]][1])
- scale = (normal[0]**2 + normal[1]**2 + normal[2]**2)**0.5
+ tri = connectivity[element_index * 3: (element_index + 1) * 3]
+ normal = (
+ c[tri[1]][1] * c[tri[2]][2] - c[tri[2]][1] * c[tri[1]][2],
+ c[tri[1]][2] * c[tri[2]][0] - c[tri[2]][2] * c[tri[1]][0],
+ c[tri[1]][0] * c[tri[2]][1] - c[tri[2]][0] * c[tri[1]][1],
+ )
+ scale = (normal[0] ** 2 + normal[1] ** 2 + normal[2] ** 2) ** 0.5
if scale > 0.0:
normal = tuple(x / scale for x in normal)
- output.write(struct.pack('<3f', *normal))
+ output.write(struct.pack("<3f", *normal))
for vertex in tri:
- output.write(struct.pack('<3f', *c[vertex]))
- output.write(struct.pack('<h', 0))
+ output.write(struct.pack("<3f", *c[vertex]))
+ output.write(struct.pack("<h", 0))
# delete the temporary block we created
self.delete_element_block(triangle_element_block_id)
@@ -1957,47 +2201,62 @@ Source code for exomerge
"""
exporters = dict()
- exporters['wrl'] = self.export_wrl_model
- exporters['stl'] = self.export_stl_file
- exporters['e'] = self.export_model
- exporters['g'] = self.export_model
- exporters['exo'] = self.export_model
- extension = filename.rsplit('.', 1)[-1].lower()
+ exporters["wrl"] = self.export_wrl_model
+ exporters["stl"] = self.export_stl_file
+ exporters["e"] = self.export_model
+ exporters["g"] = self.export_model
+ exporters["exo"] = self.export_model
+ extension = filename.rsplit(".", 1)[-1].lower()
if extension not in exporters:
self._error(
- 'Unrecognized file extension.',
+ "Unrecognized file extension.",
'The filename extension "%s" was not recognized. The '
- 'list of recognized extensions is : %s' %
- (extension, ', '.join(list(exporters.keys()))))
+ "list of recognized extensions is : %s"
+ % (extension, ", ".join(list(exporters.keys()))),
+ )
exporters[extension](filename, *args, **kwargs)
def _error_evaluating_expression(self, expression, var):
"""Throw an error saying we could not evaluate the given expression."""
self._error(
- 'Invalid expression',
- 'An error occurred while trying to evaluate the given '
- 'expression. It is likely that this expression is '
- 'ill-formed, or that the variables it uses do not '
- 'exist:\n\n%s\n\nDefined variables: %s' %
- (expression, ', '.join(sorted(var.keys()))))
+ "Invalid expression",
+ "An error occurred while trying to evaluate the given "
+ "expression. It is likely that this expression is "
+ "ill-formed, or that the variables it uses do not "
+ "exist:\n\n%s\n\nDefined variables: %s"
+ % (expression, ", ".join(sorted(var.keys()))),
+ )
@staticmethod
def _transform_eval_expression(expression, variable_names):
"""Transform a string expression into one usable by eval."""
- eval_expression = ' %s ' % expression
+ eval_expression = " %s " % expression
for name in variable_names:
- eval_expression = re.sub('([^a-zA-Z0-9_])%s([^a-zA-Z0-9_])' % name,
- r"\1var['%s']\2" % name, eval_expression)
+ eval_expression = re.sub(
+ "([^a-zA-Z0-9_])%s([^a-zA-Z0-9_])" % name,
+ r"\1var['%s']\2" % name,
+ eval_expression,
+ )
# add "math." to supported mathematical functions
# Note: abs is a built-in function, it is not math.abs
for name in [
- 'atan', 'sinh', 'cosh', 'tanh', 'exp', 'sqrt', 'sin', 'cos',
- 'tan'
+ "atan",
+ "sinh",
+ "cosh",
+ "tanh",
+ "exp",
+ "sqrt",
+ "sin",
+ "cos",
+ "tan",
]:
- eval_expression = re.sub('([^a-zA-Z0-9_])%s([^a-zA-Z0-9_])' % name,
- r'\1math.%s\2' % name, eval_expression)
+ eval_expression = re.sub(
+ "([^a-zA-Z0-9_])%s([^a-zA-Z0-9_])" % name,
+ r"\1math.%s\2" % name,
+ eval_expression,
+ )
# convert powers to from "^" to "**" format
- eval_expression = re.sub(r'\^', '**', eval_expression)
+ eval_expression = re.sub(r"\^", "**", eval_expression)
return eval_expression.strip()
[docs] def get_element_block_dimension(self, element_block_id):
@@ -2007,10 +2266,10 @@ Source code for exomerge
If this cannot be determined, return -1.
"""
[element_block_id] = self._format_element_block_id_list(
- [element_block_id], single=True)
+ [element_block_id], single=True
+ )
element_type = self._get_element_type(element_block_id)
- element_type = self._get_standard_element_type(element_type,
- warning=False)
+ element_type = self._get_standard_element_type(element_type, warning=False)
if element_type in self.DIMENSION:
return self.DIMENSION[element_type]
return -1
@@ -2018,7 +2277,8 @@ Source code for exomerge
[docs] def get_nodes_per_element(self, element_block_id):
"""Return the nodes per element in the given element block."""
[element_block_id] = self._format_element_block_id_list(
- [element_block_id], single=True)
+ [element_block_id], single=True
+ )
return self.element_blocks[element_block_id][1][2]
def _get_element_type(self, element_block_id):
@@ -2031,42 +2291,47 @@ Source code for exomerge
"""
[element_block_id] = self._format_element_block_id_list(
- [element_block_id], single=True)
+ [element_block_id], single=True
+ )
e_type = self.element_blocks[element_block_id][1][0]
if isinstance(e_type, bytes):
- return e_type.decode('utf8')
+ return e_type.decode("utf8")
return e_type
- def _calculate_element_field_extreme(self,
- element_field_names,
- element_block_ids,
- function,
- function_name,
- calculate_block_id=False,
- calculate_location=False):
+ def _calculate_element_field_extreme(
+ self,
+ element_field_names,
+ element_block_ids,
+ function,
+ function_name,
+ calculate_block_id=False,
+ calculate_location=False,
+ ):
"""Store an element field extreme as a global variable."""
- element_block_ids = self._format_element_block_id_list(
- element_block_ids)
+ element_block_ids = self._format_element_block_id_list(element_block_ids)
element_field_names = self._format_id_list(
element_field_names,
- self.get_element_field_names(element_block_ids), 'element field')
+ self.get_element_field_names(element_block_ids),
+ "element field",
+ )
for element_field_name in element_field_names:
for element_block_id in element_block_ids:
- if not self.element_field_exists(element_field_name,
- element_block_ids):
- self._missing_on_entity_error(element_field_name,
- 'element field',
- element_block_id,
- 'element block')
+ if not self.element_field_exists(element_field_name, element_block_ids):
+ self._missing_on_entity_error(
+ element_field_name,
+ "element field",
+ element_block_id,
+ "element block",
+ )
for element_field_name in element_field_names:
- name = element_field_name + '_' + function_name
+ name = element_field_name + "_" + function_name
self.create_global_variable(name)
if calculate_location:
- self.create_global_variable(name + '_x')
- self.create_global_variable(name + '_y')
- self.create_global_variable(name + '_z')
+ self.create_global_variable(name + "_x")
+ self.create_global_variable(name + "_y")
+ self.create_global_variable(name + "_z")
if calculate_block_id:
- self.create_global_variable(name + '_block_id')
+ self.create_global_variable(name + "_block_id")
for index in range(len(self.timesteps)):
extreme = None
extreme_block_id = None
@@ -2077,45 +2342,47 @@ Source code for exomerge
if not values:
continue
this_extreme = function(values)
- if (extreme is None or function([extreme, this_extreme
- ]) == this_extreme):
+ if (
+ extreme is None
+ or function([extreme, this_extreme]) == this_extreme
+ ):
extreme = this_extreme
extreme_block_id = element_block_id
connectivity = self.get_connectivity(element_block_id)
- nodes_per_element = self.get_nodes_per_element(
- element_block_id)
+ nodes_per_element = self.get_nodes_per_element(element_block_id)
element_index = values.index(extreme)
- extreme_node_indices = connectivity[element_index *
- nodes_per_element:
- (element_index +
- 1) *
- nodes_per_element]
+ extreme_node_indices = connectivity[
+ element_index
+ * nodes_per_element: (element_index + 1)
+ * nodes_per_element
+ ]
if extreme is None:
self._warning(
- 'No values encountered',
- 'The element field extreme cannot be '
- 'calculated because no values are present.')
+ "No values encountered",
+ "The element field extreme cannot be "
+ "calculated because no values are present.",
+ )
continue
self.global_variables[name][index] = extreme
if calculate_block_id:
- self.global_variables[name + '_block_id'][index] = float(
- extreme_block_id)
+ self.global_variables[name + "_block_id"][index] = float(
+ extreme_block_id
+ )
if calculate_location:
- coords = self._get_coordinates_at_time(
- self.timesteps[index])
+ coords = self._get_coordinates_at_time(self.timesteps[index])
locations = [coords[x] for x in extreme_node_indices]
- centroid = [
- self._mean([x[i] for x in locations]) for i in range(3)
- ]
- self.global_variables[name + '_x'][index] = centroid[0]
- self.global_variables[name + '_y'][index] = centroid[1]
- self.global_variables[name + '_z'][index] = centroid[2]
-
-[docs] def calculate_element_field_maximum(self,
- element_field_names,
- element_block_ids='all',
- calculate_location=False,
- calculate_block_id=False):
+ centroid = [self._mean([x[i] for x in locations]) for i in range(3)]
+ self.global_variables[name + "_x"][index] = centroid[0]
+ self.global_variables[name + "_y"][index] = centroid[1]
+ self.global_variables[name + "_z"][index] = centroid[2]
+
+[docs] def calculate_element_field_maximum(
+ self,
+ element_field_names,
+ element_block_ids="all",
+ calculate_location=False,
+ calculate_block_id=False,
+ ):
"""
Store an element field maximum as a global variable.
@@ -2134,15 +2401,18 @@ Source code for exomerge
element_field_names,
element_block_ids,
max,
- 'max',
+ "max",
calculate_location=calculate_location,
- calculate_block_id=calculate_block_id)
+ calculate_block_id=calculate_block_id,
+ )
-[docs] def calculate_element_field_minimum(self,
- element_field_names,
- element_block_ids='all',
- calculate_location=False,
- calculate_block_id=False):
+[docs] def calculate_element_field_minimum(
+ self,
+ element_field_names,
+ element_block_ids="all",
+ calculate_location=False,
+ calculate_block_id=False,
+ ):
"""
Store an element field minimum as a global variable.
@@ -2161,54 +2431,55 @@ Source code for exomerge
element_field_names,
element_block_ids,
min,
- 'min',
+ "min",
calculate_location=calculate_location,
- calculate_block_id=calculate_block_id)
-
- def _calculate_node_field_extreme(self,
- node_field_names,
- function,
- function_name,
- element_block_ids='auto',
- calculate_location=False):
+ calculate_block_id=calculate_block_id,
+ )
+
+ def _calculate_node_field_extreme(
+ self,
+ node_field_names,
+ function,
+ function_name,
+ element_block_ids="auto",
+ calculate_location=False,
+ ):
"""Store a node field extreme as a global variable."""
- node_field_names = self._format_id_list(node_field_names,
- self.get_node_field_names(),
- 'node field')
- if element_block_ids == 'auto':
+ node_field_names = self._format_id_list(
+ node_field_names, self.get_node_field_names(), "node field"
+ )
+ if element_block_ids == "auto":
node_indices = list(range(len(self.nodes)))
else:
node_indices = self.get_nodes_in_element_block(element_block_ids)
if not node_indices:
self._error(
- 'No node values',
- 'No nodes were specified, so we cannot calculate the '
- 'extreme value.')
+ "No node values",
+ "No nodes were specified, so we cannot calculate the " "extreme value.",
+ )
for node_field_name in node_field_names:
- name = node_field_name + '_' + function_name
+ name = node_field_name + "_" + function_name
self.create_global_variable(name)
if calculate_location:
- self.create_global_variable(name + '_x')
- self.create_global_variable(name + '_y')
- self.create_global_variable(name + '_z')
+ self.create_global_variable(name + "_x")
+ self.create_global_variable(name + "_y")
+ self.create_global_variable(name + "_z")
for index in range(len(self.timesteps)):
values = self.node_fields[node_field_name][index]
values = [values[x] for x in node_indices]
extreme = function(values)
self.global_variables[name][index] = extreme
if calculate_location:
- coords = self._get_coordinates_at_time(
- self.timesteps[index])
+ coords = self._get_coordinates_at_time(self.timesteps[index])
node_index = node_indices[values.index(extreme)]
location = coords[node_index]
- self.global_variables[name + '_x'][index] = location[0]
- self.global_variables[name + '_y'][index] = location[1]
- self.global_variables[name + '_z'][index] = location[2]
+ self.global_variables[name + "_x"][index] = location[0]
+ self.global_variables[name + "_y"][index] = location[1]
+ self.global_variables[name + "_z"][index] = location[2]
-[docs] def calculate_node_field_maximum(self,
- node_field_names,
- element_block_ids='auto',
- calculate_location=False):
+[docs] def calculate_node_field_maximum(
+ self, node_field_names, element_block_ids="auto", calculate_location=False
+ ):
"""
Store a node field maximum as a global variable.
@@ -2223,14 +2494,14 @@ Source code for exomerge
self._calculate_node_field_extreme(
node_field_names,
max,
- 'max',
+ "max",
element_block_ids=element_block_ids,
- calculate_location=calculate_location)
+ calculate_location=calculate_location,
+ )
-[docs] def calculate_node_field_minimum(self,
- node_field_names,
- element_block_ids='auto',
- calculate_location=False):
+[docs] def calculate_node_field_minimum(
+ self, node_field_names, element_block_ids="auto", calculate_location=False
+ ):
"""
Store a node field minimum as a global variable.
@@ -2245,14 +2516,14 @@ Source code for exomerge
self._calculate_node_field_extreme(
node_field_names,
min,
- 'min',
+ "min",
element_block_ids=element_block_ids,
- calculate_location=calculate_location)
+ calculate_location=calculate_location,
+ )
-[docs] def output_global_variables(self,
- filename=None,
- global_variable_names='all',
- timesteps='all'):
+[docs] def output_global_variables(
+ self, filename=None, global_variable_names="all", timesteps="all"
+ ):
"""
Output global variables in CSV format.
@@ -2269,24 +2540,23 @@ Source code for exomerge
"""
global_variable_names = self._format_id_list(
- global_variable_names, self.get_global_variable_names(),
- 'global variable')
- timesteps = self._format_id_list(timesteps, self.get_timesteps(),
- 'timestep')
+ global_variable_names, self.get_global_variable_names(), "global variable"
+ )
+ timesteps = self._format_id_list(timesteps, self.get_timesteps(), "timestep")
# output header
- names = ['time']
+ names = ["time"]
names.extend(global_variable_names)
- output = ', '.join(names) + '\n'
+ output = ", ".join(names) + "\n"
# output values
for timestep in timesteps:
index = self.timesteps.index(timestep)
values = [timestep]
for name in global_variable_names:
values.append(self.global_variables[name][index])
- output += ', '.join(str(x) for x in values) + '\n'
+ output += ", ".join(str(x) for x in values) + "\n"
# output to file or screen
if filename:
- open(filename, 'w').write(output)
+ open(filename, "w").write(output)
else:
if output:
output = output[:-1]
@@ -2305,31 +2575,32 @@ Source code for exomerge
>>> model.calculate_global_variable('total = potential + kinetic')
"""
- if '=' not in expression:
+ if "=" not in expression:
self._error(
- 'Invalid expression',
+ "Invalid expression",
'A "=" sign must be present in the expression but '
- 'was not found.\n\nExpression: %s' % expression)
- (name, expression) = expression.split('=', 1)
+ "was not found.\n\nExpression: %s" % expression,
+ )
+ (name, expression) = expression.split("=", 1)
new_name = name.strip()
self.create_global_variable(new_name)
# create list of variable names and modify them in the expression
- variable_names = set(['time'])
+ variable_names = set(["time"])
variable_names.update(self.get_global_variable_names())
- eval_expression = self._transform_eval_expression(
- expression, variable_names)
- function = eval('lambda var: ' + eval_expression)
+ eval_expression = self._transform_eval_expression(expression, variable_names)
+ function = eval("lambda var: " + eval_expression)
var = dict()
try:
for index, time in enumerate(self.timesteps):
- var['time'] = time
+ var["time"] = time
for name, values in list(self.global_variables.items()):
var[name] = values[index]
value = float(function(var))
self.global_variables[new_name][index] = value
except (SyntaxError, NameError):
self._error_evaluating_expression(
- "%s = %s" % (new_name, eval_expression), var)
+ "%s = %s" % (new_name, eval_expression), var
+ )
[docs] def calculate_node_field(self, expression):
"""
@@ -2345,37 +2616,37 @@ Source code for exomerge
>>> model.calculate_node_field('temp_C = temp_K - 273.15')
"""
- if '=' not in expression:
+ if "=" not in expression:
self._error(
- 'Invalid expression',
+ "Invalid expression",
'A "=" sign must be present in the expression but '
- 'was not found.\n\nExpression: %s' % expression)
- (name, expression) = expression.split('=', 1)
+ "was not found.\n\nExpression: %s" % expression,
+ )
+ (name, expression) = expression.split("=", 1)
new_name = name.strip()
self.create_node_field(new_name)
new_values = self.node_fields[new_name]
# create list of variable names and modify them in the expression
- variable_names = set(['time'])
- variable_names.update(['X', 'Y', 'Z'])
+ variable_names = set(["time"])
+ variable_names.update(["X", "Y", "Z"])
variable_names.update(self.get_global_variable_names())
variable_names.update(self.get_node_field_names())
- eval_expression = self._transform_eval_expression(
- expression, variable_names)
+ eval_expression = self._transform_eval_expression(expression, variable_names)
var = dict()
- function = eval('lambda var: ' + eval_expression)
+ function = eval("lambda var: " + eval_expression)
try:
for time_index, time in enumerate(self.timesteps):
# set time
- var['time'] = time
+ var["time"] = time
# set global variables
for name, values in list(self.global_variables.items()):
var[name] = values[time_index]
# go through each node
for node_index in range(len(self.nodes)):
# set coordinate values
- var['X'] = self.nodes[node_index][0]
- var['Y'] = self.nodes[node_index][1]
- var['Z'] = self.nodes[node_index][2]
+ var["X"] = self.nodes[node_index][0]
+ var["Y"] = self.nodes[node_index][1]
+ var["Z"] = self.nodes[node_index][2]
# set node field values
for name, values in list(self.node_fields.items()):
var[name] = values[time_index][node_index]
@@ -2383,9 +2654,10 @@ Source code for exomerge
new_values[time_index][node_index] = value
except (SyntaxError, NameError):
self._error_evaluating_expression(
- "%s = %s" % (new_name, eval_expression), var)
+ "%s = %s" % (new_name, eval_expression), var
+ )
-[docs] def calculate_node_set_field(self, expression, node_set_ids='all'):
+[docs] def calculate_node_set_field(self, expression, node_set_ids="all"):
"""
Store a node set field calculated from the given expression.
@@ -2401,12 +2673,13 @@ Source code for exomerge
"""
node_set_ids = self._format_node_set_id_list(node_set_ids)
- if '=' not in expression:
+ if "=" not in expression:
self._error(
- 'Invalid expression',
+ "Invalid expression",
'A "=" sign must be present in the expression but '
- 'was not found.\n\nExpression: %s' % expression)
- (name, expression) = expression.split('=', 1)
+ "was not found.\n\nExpression: %s" % expression,
+ )
+ (name, expression) = expression.split("=", 1)
new_name = name.strip()
# for each node set
for node_set_id in node_set_ids:
@@ -2415,28 +2688,29 @@ Source code for exomerge
fields = self._get_node_set_fields(node_set_id)
new_values = fields[new_name]
# create list of variable names and modify them in the expression
- variable_names = set(['time'])
- variable_names.update(['X', 'Y', 'Z'])
+ variable_names = set(["time"])
+ variable_names.update(["X", "Y", "Z"])
variable_names.update(self.get_global_variable_names())
variable_names.update(self.get_node_field_names())
variable_names.update(list(fields.keys()))
eval_expression = self._transform_eval_expression(
- expression, variable_names)
- function = eval('lambda var: ' + eval_expression)
+ expression, variable_names
+ )
+ function = eval("lambda var: " + eval_expression)
var = dict()
try:
for time_index, time in enumerate(self.timesteps):
# set time
- var['time'] = time
+ var["time"] = time
# set global variables
for name, values in list(self.global_variables.items()):
var[name] = values[time_index]
# go through each node
for member_index, node_index in enumerate(members):
# set coordinate values
- var['X'] = self.nodes[node_index][0]
- var['Y'] = self.nodes[node_index][1]
- var['Z'] = self.nodes[node_index][2]
+ var["X"] = self.nodes[node_index][0]
+ var["Y"] = self.nodes[node_index][1]
+ var["Z"] = self.nodes[node_index][2]
# set node fields
for name, values in list(self.node_fields.items()):
var[name] = values[time_index][node_index]
@@ -2447,9 +2721,10 @@ Source code for exomerge
new_values[time_index][member_index] = value
except (SyntaxError, NameError):
self._error_evaluating_expression(
- "%s = %s" % (new_name, eval_expression), var)
+ "%s = %s" % (new_name, eval_expression), var
+ )
-[docs] def calculate_side_set_field(self, expression, side_set_ids='all'):
+[docs] def calculate_side_set_field(self, expression, side_set_ids="all"):
"""
Store a side set field calculated from the given expression.
@@ -2462,12 +2737,13 @@ Source code for exomerge
"""
side_set_ids = self._format_side_set_id_list(side_set_ids)
- if '=' not in expression:
+ if "=" not in expression:
self._error(
- 'Invalid expression',
+ "Invalid expression",
'A "=" sign must be present in the expression but '
- 'was not found.\n\nExpression: %s' % expression)
- (name, expression) = expression.split('=', 1)
+ "was not found.\n\nExpression: %s" % expression,
+ )
+ (name, expression) = expression.split("=", 1)
new_name = name.strip()
# for each side set
for side_set_id in side_set_ids:
@@ -2476,17 +2752,18 @@ Source code for exomerge
fields = self._get_side_set_fields(side_set_id)
new_values = fields[new_name]
# create list of variable names and modify them in the expression
- variable_names = set(['time'])
+ variable_names = set(["time"])
variable_names.update(self.get_global_variable_names())
variable_names.update(list(fields.keys()))
eval_expression = self._transform_eval_expression(
- expression, variable_names)
- function = eval('lambda var: ' + eval_expression)
+ expression, variable_names
+ )
+ function = eval("lambda var: " + eval_expression)
var = dict()
try:
for time_index, time in enumerate(self.timesteps):
# set time
- var['time'] = time
+ var["time"] = time
# set global variables
for name, values in list(self.global_variables.items()):
var[name] = values[time_index]
@@ -2499,9 +2776,10 @@ Source code for exomerge
new_values[time_index][member_index] = value
except (SyntaxError, NameError):
self._error_evaluating_expression(
- "%s = %s" % (new_name, eval_expression), var)
+ "%s = %s" % (new_name, eval_expression), var
+ )
-[docs] def calculate_element_field(self, expression, element_block_ids='all'):
+[docs] def calculate_element_field(self, expression, element_block_ids="all"):
"""
Store an element field calculated from the given expression.
@@ -2515,14 +2793,14 @@ Source code for exomerge
... 'stress_yy + stress_zz) / -3')
"""
- element_block_ids = self._format_element_block_id_list(
- element_block_ids)
- if '=' not in expression:
+ element_block_ids = self._format_element_block_id_list(element_block_ids)
+ if "=" not in expression:
self._error(
- 'Invalid expression',
+ "Invalid expression",
'A "=" sign must be present in the expression but '
- 'was not found.\n\nExpression: %s' % expression)
- (name, expression) = expression.split('=', 1)
+ "was not found.\n\nExpression: %s" % expression,
+ )
+ (name, expression) = expression.split("=", 1)
new_name = name.strip()
# for each element block
for element_block_id in element_block_ids:
@@ -2531,17 +2809,18 @@ Source code for exomerge
element_count = self.get_element_count(element_block_id)
new_values = fields[new_name]
# create list of variable names and modify them in the expression
- variable_names = set(['time'])
+ variable_names = set(["time"])
variable_names.update(self.get_global_variable_names())
variable_names.update(list(fields.keys()))
eval_expression = self._transform_eval_expression(
- expression, variable_names)
- function = eval('lambda var: ' + eval_expression)
+ expression, variable_names
+ )
+ function = eval("lambda var: " + eval_expression)
var = dict()
try:
for time_index, time in enumerate(self.timesteps):
# set time
- var['time'] = time
+ var["time"] = time
# set global variables
for name, values in list(self.global_variables.items()):
var[name] = values[time_index]
@@ -2554,7 +2833,8 @@ Source code for exomerge
new_values[time_index][index] = value
except (SyntaxError, NameError):
self._error_evaluating_expression(
- "%s = %s" % (new_name, eval_expression), var)
+ "%s = %s" % (new_name, eval_expression), var
+ )
[docs] def to_lowercase(self):
"""
@@ -2595,44 +2875,50 @@ Source code for exomerge
"""
# validity check the inputs
valid_element_block_translation_list = []
- for (id_, new_element_type) in element_block_translation_list:
+ for id_, new_element_type in element_block_translation_list:
# check if element block exists
if not self.element_block_exists(id_):
- self._missing_warning(id_, 'element block')
+ self._missing_warning(id_, "element block")
continue
old_element_type = self._get_standard_element_type(
- self._get_element_type(id_))
+ self._get_element_type(id_)
+ )
# check if any schemes exist for this element block
if old_element_type not in self.ELEMENT_CONVERSIONS:
self._error(
- 'No element conversion schemes',
- 'There are no element conversion schemes to '
+ "No element conversion schemes",
+ "There are no element conversion schemes to "
'convert elements of type "%s" into any other '
- 'element type.' % (old_element_type))
+ "element type." % (old_element_type),
+ )
continue
# check if the given scheme exists for this element block
conversions = self.ELEMENT_CONVERSIONS[old_element_type]
if new_element_type not in conversions:
self._error(
- 'Invalid target element type',
- 'There are no element conversion schemes to '
+ "Invalid target element type",
+ "There are no element conversion schemes to "
'convert elements of type "%s" into elements of '
'type "%s". Conversions are available to the '
- 'following element types: "%s".' %
- (old_element_type, new_element_type, '", "'.join(
- list(conversions.keys()))))
+ 'following element types: "%s".'
+ % (
+ old_element_type,
+ new_element_type,
+ '", "'.join(list(conversions.keys())),
+ ),
+ )
continue
# all is good, keep this one on the list
- valid_element_block_translation_list.append(
- [id_, new_element_type])
+ valid_element_block_translation_list.append([id_, new_element_type])
# if we have nothing to do, just exit
if not valid_element_block_translation_list:
return
# now we need to find the new nodes to create, if any
averaged_nodes = set()
- for (id_, new_element_type) in valid_element_block_translation_list:
+ for id_, new_element_type in valid_element_block_translation_list:
old_element_type = self._get_standard_element_type(
- self._get_element_type(id_))
+ self._get_element_type(id_)
+ )
scheme = self.ELEMENT_CONVERSIONS[old_element_type]
scheme = scheme[new_element_type]
# find new nodes which need created
@@ -2650,8 +2936,8 @@ Source code for exomerge
nodes_per_element = self.get_nodes_per_element(id_)
# iterate over each element
for local_node in [
- connectivity[x:x + nodes_per_element]
- for x in range(0, len(connectivity), nodes_per_element)
+ connectivity[x: x + nodes_per_element]
+ for x in range(0, len(connectivity), nodes_per_element)
]:
# iterate over each new averaged node formula
for formula in averaged_node_list:
@@ -2659,15 +2945,16 @@ Source code for exomerge
averaged_nodes.add(node_list)
# create the averaged node mapping
averaged_nodes = sorted(averaged_nodes)
- averaged_node_map = dict((x, len(self.nodes) + index)
- for index, x in enumerate(averaged_nodes))
+ averaged_node_map = dict(
+ (x, len(self.nodes) + index) for index, x in enumerate(averaged_nodes)
+ )
# create new averaged nodes
self._create_averaged_nodes(averaged_nodes, [])
# now create the new element blocks
- for (element_block_id,
- new_element_type) in valid_element_block_translation_list:
+ for element_block_id, new_element_type in valid_element_block_translation_list:
old_element_type = self._get_standard_element_type(
- self._get_element_type(element_block_id))
+ self._get_element_type(element_block_id)
+ )
scheme = self.ELEMENT_CONVERSIONS[old_element_type]
scheme = scheme[new_element_type]
# rename some things
@@ -2676,37 +2963,42 @@ Source code for exomerge
# create the connectivity for the new element block
new_connectivity = []
for local_node in [
- connectivity[x:x + nodes_per_element]
- for x in range(0, len(connectivity), nodes_per_element)
+ connectivity[x: x + nodes_per_element]
+ for x in range(0, len(connectivity), nodes_per_element)
]:
for new_element in scheme:
for new_node in new_element:
if isinstance(new_node, int):
new_connectivity.append(local_node[new_node])
else:
- node_list = tuple(
- sorted(local_node[x] for x in new_node))
- new_connectivity.append(
- averaged_node_map[node_list])
+ node_list = tuple(sorted(local_node[x] for x in new_node))
+ new_connectivity.append(averaged_node_map[node_list])
# create a temporary element block
temporary_element_block_id = self._new_element_block_id()
new_nodes_per_element = self.NODES_PER_ELEMENT[new_element_type]
- self.create_element_block(temporary_element_block_id, [
- new_element_type,
- len(new_connectivity) // new_nodes_per_element,
- new_nodes_per_element, 0
- ], new_connectivity)
+ self.create_element_block(
+ temporary_element_block_id,
+ [
+ new_element_type,
+ len(new_connectivity) // new_nodes_per_element,
+ new_nodes_per_element,
+ 0,
+ ],
+ new_connectivity,
+ )
temporary_fields = self._get_element_block_fields(
- temporary_element_block_id)
+ temporary_element_block_id
+ )
element_multiplier = len(scheme)
# transfer element values
fields = self._get_element_block_fields(element_block_id)
for field_name in self.get_element_field_names(element_block_id):
values = fields[field_name]
new_values = [list(x) for x in values]
- new_values = [[
- x for x in these_values for _ in range(element_multiplier)
- ] for these_values in new_values]
+ new_values = [
+ [x for x in these_values for _ in range(element_multiplier)]
+ for these_values in new_values
+ ]
temporary_fields[field_name] = new_values
# for each face in the old scheme, find all of its nodes
old_face_mapping = self._get_face_mapping(old_element_type)
@@ -2714,8 +3006,7 @@ Source code for exomerge
new_face_mapping = self._get_face_mapping(new_element_type)
face_translation = [[] for _ in range(len(old_face_nodes))]
for new_element_index, new_element in enumerate(scheme):
- for new_face_index, (
- _, face_members) in enumerate(new_face_mapping):
+ for new_face_index, (_, face_members) in enumerate(new_face_mapping):
# find all nodes used by this new face
used_nodes = set()
for face_member in face_members:
@@ -2724,25 +3015,29 @@ Source code for exomerge
else:
used_nodes.update(new_element[face_member])
# see if these are a subset of nodes in the old set
- for (old_face_index,
- old_members) in enumerate(old_face_nodes):
+ for old_face_index, old_members in enumerate(old_face_nodes):
if used_nodes <= old_members:
face_translation[old_face_index].append(
- (new_element_index, new_face_index))
+ (new_element_index, new_face_index)
+ )
# update self.side_sets
for id_ in self.get_side_set_ids():
members = self.get_side_set_members(id_)
fields = self._get_side_set_fields(id_)
old_members = list(members)
- for member_index, (block_id, element_index,
- face_index) in enumerate(old_members):
+ for member_index, (block_id, element_index, face_index) in enumerate(
+ old_members
+ ):
if block_id == element_block_id:
# add some new faces
for new_faces in face_translation[face_index]:
members.append(
- (temporary_element_block_id,
- element_index * len(scheme) + new_faces[0],
- new_faces[1]))
+ (
+ temporary_element_block_id,
+ element_index * len(scheme) + new_faces[0],
+ new_faces[1],
+ )
+ )
# add values for the new faces
for all_values in list(fields.values()):
for values in all_values:
@@ -2751,16 +3046,13 @@ Source code for exomerge
# delete the old block
self.delete_element_block(element_block_id)
# rename the temporary element block
- self.rename_element_block(temporary_element_block_id,
- element_block_id)
+ self.rename_element_block(temporary_element_block_id, element_block_id)
[docs] def convert_element_blocks(self, element_block_ids, new_element_type):
"""Convert elements within a block to a new element type."""
- element_block_ids = self._format_element_block_id_list(
- element_block_ids)
+ element_block_ids = self._format_element_block_id_list(element_block_ids)
# form the conversion list
- conversion_list = [(id_, new_element_type)
- for id_ in element_block_ids]
+ conversion_list = [(id_, new_element_type) for id_ in element_block_ids]
# convert each block
self._translate_element_blocks(conversion_list)
@@ -2774,21 +3066,20 @@ Source code for exomerge
the fewest nodes.
"""
- element_block_ids = self._format_element_block_id_list(
- element_block_ids)
+ element_block_ids = self._format_element_block_id_list(element_block_ids)
# find all element types we need to convert
element_types = set()
for element_block_id in element_block_ids:
element_types.add(self._get_element_type(element_block_id))
element_types = sorted(
- self._get_standard_element_type(x) for x in element_types)
+ self._get_standard_element_type(x) for x in element_types
+ )
# ignore non-standard element types
- element_types = [
- x for x in element_types if x in self.STANDARD_ELEMENT_TYPES
- ]
+ element_types = [x for x in element_types if x in self.STANDARD_ELEMENT_TYPES]
# find all elements of the target order
target_element_types = [
- x for x in self.STANDARD_ELEMENT_TYPES
+ x
+ for x in self.STANDARD_ELEMENT_TYPES
if self.ELEMENT_ORDER[x] == target_order
]
# for each element type, find the optimal target type
@@ -2800,26 +3091,29 @@ Source code for exomerge
if self.ELEMENT_ORDER[element_type] == target_order:
continue
self._error(
- 'Unable to convert',
- 'There is no valid scheme to convert elements '
+ "Unable to convert",
+ "There is no valid scheme to convert elements "
'of type "%s" to an element type of order '
- '%d.' % (element_type, target_order))
+ "%d." % (element_type, target_order),
+ )
scheme = self.ELEMENT_CONVERSIONS[element_type]
- possible_types = set(
- scheme.keys()).intersection(target_element_types)
+ possible_types = set(scheme.keys()).intersection(target_element_types)
if not possible_types:
# if element type is already the desired order, no warning
if self.ELEMENT_ORDER[element_type] == target_order:
continue
self._error(
- 'Unable to convert',
- 'There is no valid scheme to convert elements '
+ "Unable to convert",
+ "There is no valid scheme to convert elements "
'of type "%s" to an element type of order '
- '%d.' % (element_type, target_order))
+ "%d." % (element_type, target_order),
+ )
# out of the given options, choose the one that first creates the
# least number of elements, and secondly the least number of nodes
- ranking = [(len(scheme[x]), len(scheme[x]) * len(scheme[x][0]), x)
- for x in possible_types]
+ ranking = [
+ (len(scheme[x]), len(scheme[x]) * len(scheme[x][0]), x)
+ for x in possible_types
+ ]
ranking = sorted(ranking)
element_type_map[element_type] = ranking[0][-1]
# create the conversion list
@@ -2829,11 +3123,12 @@ Source code for exomerge
element_type = self._get_standard_element_type(element_type)
if element_type in element_type_map:
conversion_list.append(
- (element_block_id, element_type_map[element_type]))
+ (element_block_id, element_type_map[element_type])
+ )
# now translate the elements
self._translate_element_blocks(conversion_list)
-[docs] def make_elements_linear(self, element_block_ids='all'):
+[docs] def make_elements_linear(self, element_block_ids="all"):
"""
Convert elements in one or more element blocks to a linear type.
@@ -2845,7 +3140,7 @@ Source code for exomerge
"""
self._change_element_order(element_block_ids, 1)
-[docs] def make_elements_quadratic(self, element_block_ids='all'):
+[docs] def make_elements_quadratic(self, element_block_ids="all"):
"""
Convert elements in one or more element blocks to a quadratic type.
@@ -2857,13 +3152,14 @@ Source code for exomerge
"""
self._change_element_order(element_block_ids, 2)
- def _translate_element_type(self, element_block_id, new_element_type,
- scheme):
+ def _translate_element_type(self, element_block_id, new_element_type, scheme):
"""Convert elements within a block to a new type."""
[element_block_id] = self._format_element_block_id_list(
- [element_block_id], single=True)
+ [element_block_id], single=True
+ )
old_element_type = self._get_standard_element_type(
- self._get_element_type(element_block_id))
+ self._get_element_type(element_block_id)
+ )
new_element_type = self._get_standard_element_type(new_element_type)
old_nodes_per_element = self.NODES_PER_ELEMENT[old_element_type]
new_nodes_per_element = self.NODES_PER_ELEMENT[new_element_type]
@@ -2876,17 +3172,17 @@ Source code for exomerge
connectivity = self.get_connectivity(element_block_id)
element_count = self.get_element_count(element_block_id)
for element_index in range(element_count):
- local_node = connectivity[element_index *
- old_nodes_per_element:(element_index +
- 1) *
- old_nodes_per_element]
+ local_node = connectivity[
+ element_index
+ * old_nodes_per_element: (element_index + 1)
+ * old_nodes_per_element
+ ]
for new_element in scheme:
for new_node in new_element:
if isinstance(new_node, int):
duplicate_nodes.add(local_node[new_node])
else:
- averaged_nodes.add(
- tuple(local_node[x] for x in new_node))
+ averaged_nodes.add(tuple(local_node[x] for x in new_node))
# create new nodes
next_node_index = len(self.nodes)
duplicate_nodes = sorted(duplicate_nodes)
@@ -2894,43 +3190,53 @@ Source code for exomerge
self._duplicate_nodes(duplicate_nodes, [])
self._create_averaged_nodes(averaged_nodes, [])
# assign node indices
- duplicate_nodes = dict((x, next_node_index + index)
- for index, x in enumerate(duplicate_nodes))
+ duplicate_nodes = dict(
+ (x, next_node_index + index) for index, x in enumerate(duplicate_nodes)
+ )
next_node_index += len(duplicate_nodes)
- averaged_nodes = dict((x, next_node_index + index)
- for index, x in enumerate(averaged_nodes))
+ averaged_nodes = dict(
+ (x, next_node_index + index) for index, x in enumerate(averaged_nodes)
+ )
# create the connectivity for the new element block
new_connectivity = []
for element_index in range(element_count):
- local_node = connectivity[element_index *
- old_nodes_per_element:(element_index +
- 1) *
- old_nodes_per_element]
+ local_node = connectivity[
+ element_index
+ * old_nodes_per_element: (element_index + 1)
+ * old_nodes_per_element
+ ]
for new_element in scheme:
for new_node in new_element:
if isinstance(new_node, int):
- new_connectivity.append(
- duplicate_nodes[local_node[new_node]])
+ new_connectivity.append(duplicate_nodes[local_node[new_node]])
else:
- new_connectivity.append(averaged_nodes[tuple(
- local_node[x] for x in new_node)])
+ new_connectivity.append(
+ averaged_nodes[tuple(local_node[x] for x in new_node)]
+ )
# create the new block
temporary_element_block_id = self._new_element_block_id()
- self.create_element_block(temporary_element_block_id, [
- new_element_type,
- len(new_connectivity) // new_nodes_per_element,
- new_nodes_per_element, 0
- ], new_connectivity)
+ self.create_element_block(
+ temporary_element_block_id,
+ [
+ new_element_type,
+ len(new_connectivity) // new_nodes_per_element,
+ new_nodes_per_element,
+ 0,
+ ],
+ new_connectivity,
+ )
temporary_element_fields = self._get_element_block_fields(
- temporary_element_block_id)
+ temporary_element_block_id
+ )
# transfer element values
fields = self._get_element_block_fields(element_block_id)
for field_name in self.get_element_field_names(element_block_id):
values = fields[field_name]
new_values = [list(x) for x in values]
- new_values = [[
- x for x in these_values for _ in range(element_multiplier)
- ] for these_values in new_values]
+ new_values = [
+ [x for x in these_values for _ in range(element_multiplier)]
+ for these_values in new_values
+ ]
temporary_element_fields[field_name] = new_values
# for each face in the old scheme, find all of its nodes
old_face_mapping = self._get_face_mapping(old_element_type)
@@ -2938,8 +3244,7 @@ Source code for exomerge
new_face_mapping = self._get_face_mapping(new_element_type)
face_translation = [[] for _ in range(len(old_face_nodes))]
for new_element_index, new_element in enumerate(scheme):
- for new_face_index, (_,
- face_members) in enumerate(new_face_mapping):
+ for new_face_index, (_, face_members) in enumerate(new_face_mapping):
# find all nodes used by this new face
used_nodes = set()
for face_member in face_members:
@@ -2951,21 +3256,26 @@ Source code for exomerge
for old_face_index, old_members in enumerate(old_face_nodes):
if used_nodes <= old_members:
face_translation[old_face_index].append(
- (new_element_index, new_face_index))
+ (new_element_index, new_face_index)
+ )
# update self.side_sets
for side_set_id in self.get_side_set_ids():
members = self.get_side_set_members(side_set_id)
fields = self._get_side_set_fields(side_set_id)
old_members = list(members)
- for member_index, (block_id, element_index,
- face_index) in enumerate(old_members):
+ for member_index, (block_id, element_index, face_index) in enumerate(
+ old_members
+ ):
if block_id == element_block_id:
# add some new faces
for new_faces in face_translation[face_index]:
members.append(
- (temporary_element_block_id,
- element_index * len(scheme) + new_faces[0],
- new_faces[1]))
+ (
+ temporary_element_block_id,
+ element_index * len(scheme) + new_faces[0],
+ new_faces[1],
+ )
+ )
# add values for the new faces
for all_values in list(fields.values()):
for values in all_values:
@@ -2975,9 +3285,7 @@ Source code for exomerge
self.delete_element_block(element_block_id)
self.rename_element_block(temporary_element_block_id, element_block_id)
-[docs] def convert_hex8_block_to_tet4_block(self,
- element_block_id,
- scheme='hex24tet'):
+[docs] def convert_hex8_block_to_tet4_block(self, element_block_id, scheme="hex24tet"):
"""
Convert a block of 'hex8' elements to a block of 'tet4' elements.
@@ -2993,32 +3301,40 @@ Source code for exomerge
"""
[element_block_id] = self._format_element_block_id_list(
- [element_block_id], single=True)
+ [element_block_id], single=True
+ )
# ensure source block is actually hex8
source_element_type = self._get_standard_element_type(
- self._get_element_type(element_block_id))
- if source_element_type != 'hex8':
+ self._get_element_type(element_block_id)
+ )
+ if source_element_type != "hex8":
self._error(
- 'Incompatible element type.',
- 'We were expecting an element block composed of '
+ "Incompatible element type.",
+ "We were expecting an element block composed of "
'"hex8" element but instead encountered one with "%s" '
- 'elements.' % source_element_type)
+ "elements." % source_element_type,
+ )
# get the chosen scheme
- if scheme != 'hex24tet':
- self._error('Unsupported scheme.',
- 'The scheme "%s" was not recognized.' % scheme)
+ if scheme != "hex24tet":
+ self._error(
+ "Unsupported scheme.", 'The scheme "%s" was not recognized.' % scheme
+ )
# create the scheme
scheme = []
- for _, face in self._get_face_mapping('hex8'):
+ for _, face in self._get_face_mapping("hex8"):
for index in range(4):
scheme.append(
- tuple([
- face[(index + 1) % 4], face[index],
- tuple(sorted(face)),
- tuple(range(8))
- ]))
+ tuple(
+ [
+ face[(index + 1) % 4],
+ face[index],
+ tuple(sorted(face)),
+ tuple(range(8)),
+ ]
+ )
+ )
# apply it
- self._translate_element_type(element_block_id, 'tet4', scheme)
+ self._translate_element_type(element_block_id, "tet4", scheme)
[docs] def displacement_field_exists(self):
"""
@@ -3029,9 +3345,11 @@ Source code for exomerge
"""
prefix = self._get_displacement_field_prefix()
- return (self.node_field_exists(prefix + '_x')
- and self.node_field_exists(prefix + '_y')
- and self.node_field_exists(prefix + '_z'))
+ return (
+ self.node_field_exists(prefix + "_x")
+ and self.node_field_exists(prefix + "_y")
+ and self.node_field_exists(prefix + "_z")
+ )
[docs] def create_displacement_field(self):
"""
@@ -3042,8 +3360,8 @@ Source code for exomerge
"""
prefix = self._get_displacement_field_prefix()
- for component in ['x', 'y', 'z']:
- this_name = prefix + '_' + component
+ for component in ["x", "y", "z"]:
+ this_name = prefix + "_" + component
if not self.node_field_exists(this_name):
self.create_node_field(this_name)
@@ -3057,12 +3375,12 @@ Source code for exomerge
self.create_displacement_field()
prefix = self._get_displacement_field_prefix()
displacement_field_list = []
- for component in ['x', 'y', 'z']:
- this_name = prefix + '_' + component
+ for component in ["x", "y", "z"]:
+ this_name = prefix + "_" + component
displacement_field_list.append(self.node_fields[this_name])
return displacement_field_list
- def _apply_displacements(self, timestep='last', scale_factor=1.0):
+ def _apply_displacements(self, timestep="last", scale_factor=1.0):
"""
Apply the displacements to each node.
@@ -3076,13 +3394,13 @@ Source code for exomerge
is unchanged.
"""
- timestep = self._format_id_list(timestep, self.get_timesteps(),
- 'timestep')
+ timestep = self._format_id_list(timestep, self.get_timesteps(), "timestep")
if len(timestep) > 1:
self._error(
- 'Ambiguous timestep.',
- 'More than one timestep was specified. We expected '
- 'one or zero timesteps.')
+ "Ambiguous timestep.",
+ "More than one timestep was specified. We expected "
+ "one or zero timesteps.",
+ )
if not timestep:
return [tuple(x) for x in self.nodes]
timestep_index = self.timesteps.index(timestep[0])
@@ -3090,13 +3408,12 @@ Source code for exomerge
x[timestep_index] for x in self._get_displacement_field_values()
]
new_nodes = [
- (x + dx * scale_factor, y + dy * scale_factor,
- z + dz * scale_factor)
+ (x + dx * scale_factor, y + dy * scale_factor, z + dz * scale_factor)
for (x, y, z), dx, dy, dz in zip(self.nodes, *displacement_values)
]
self.nodes = new_nodes
- def _get_local_index(self, this_id, id_list, entity='entity'):
+ def _get_local_index(self, this_id, id_list, entity="entity"):
"""
Return the local index corresponding to the given id.
@@ -3109,33 +3426,35 @@ Source code for exomerge
10
"""
- if this_id == 'first':
+ if this_id == "first":
if not id_list:
self._error(
- 'Undefined %s reference.' % entity,
- 'A reference to the first %s was encountered but '
- 'no %ss are defined.' % (entity, entity))
+ "Undefined %s reference." % entity,
+ "A reference to the first %s was encountered but "
+ "no %ss are defined." % (entity, entity),
+ )
return 0
- if this_id == 'last':
+ if this_id == "last":
if not id_list:
self._error(
- 'Undefined %s reference.' % entity,
- 'A reference to the last %s was encountered but '
- 'no %ss are defined.' % (entity, entity))
+ "Undefined %s reference." % entity,
+ "A reference to the last %s was encountered but "
+ "no %ss are defined." % (entity, entity),
+ )
return len(id_list) - 1
if this_id not in id_list:
- entity_list = ', '.join([str(x) for x in id_list])
+ entity_list = ", ".join([str(x) for x in id_list])
self._error(
- 'Reference to undefined %s.' % entity,
+ "Reference to undefined %s." % entity,
'A reference to %s "%s" was encountered but is not '
- 'defined in the model. There are %d defined %ss: %s' %
- (entity, str(this_id), len(id_list), entity, entity_list))
+ "defined in the model. There are %d defined %ss: %s"
+ % (entity, str(this_id), len(id_list), entity, entity_list),
+ )
return id_list.index(this_id)
-[docs] def get_element_field_values(self,
- element_field_name,
- element_block_id='auto',
- timestep='last'):
+[docs] def get_element_field_values(
+ self, element_field_name, element_block_id="auto", timestep="last"
+ ):
"""
Return the list of element field values.
@@ -3153,25 +3472,26 @@ Source code for exomerge
[element_field_name] = self._format_id_list(
[element_field_name],
self.get_element_field_names(),
- 'element field',
- single=True)
+ "element field",
+ single=True,
+ )
[element_block_id] = self._format_element_block_id_list(
- [element_block_id], single=True)
- [timestep] = self._format_id_list([timestep],
- self.get_timesteps(),
- 'timestep',
- single=True)
+ [element_block_id], single=True
+ )
+ [timestep] = self._format_id_list(
+ [timestep], self.get_timesteps(), "timestep", single=True
+ )
timestep_index = self._get_internal_timestep_index(timestep)
if not self.element_field_exists(element_field_name, element_block_id):
- self._missing_on_entity_error(element_field_name, 'element field',
- element_block_id, 'element block')
+ self._missing_on_entity_error(
+ element_field_name, "element field", element_block_id, "element block"
+ )
fields = self._get_element_block_fields(element_block_id)
return fields[element_field_name][timestep_index]
-[docs] def get_side_set_field_values(self,
- side_set_field_name,
- side_set_id='auto',
- timestep='last'):
+[docs] def get_side_set_field_values(
+ self, side_set_field_name, side_set_id="auto", timestep="last"
+ ):
"""
Return the list of side set field values.
@@ -3190,24 +3510,23 @@ Source code for exomerge
[side_set_field_name] = self._format_id_list(
[side_set_field_name],
self.get_side_set_field_names(),
- 'side set field',
- single=True)
- [timestep] = self._format_id_list([timestep],
- self.get_timesteps(),
- 'timestep',
- single=True)
+ "side set field",
+ single=True,
+ )
+ [timestep] = self._format_id_list(
+ [timestep], self.get_timesteps(), "timestep", single=True
+ )
timestep_index = self._get_internal_timestep_index(timestep)
if not self.side_set_field_exists(side_set_field_name, side_set_id):
- self._missing_on_entity_error(side_set_field_name,
- 'side set field', side_set_id,
- 'side set')
+ self._missing_on_entity_error(
+ side_set_field_name, "side set field", side_set_id, "side set"
+ )
fields = self._get_side_set_fields(side_set_id)
return fields[side_set_field_name][timestep_index]
-[docs] def get_node_set_field_values(self,
- node_set_field_name,
- node_set_id='auto',
- timestep='last'):
+[docs] def get_node_set_field_values(
+ self, node_set_field_name, node_set_id="auto", timestep="last"
+ ):
"""
Return the list of node set field values.
@@ -3226,17 +3545,17 @@ Source code for exomerge
[node_set_field_name] = self._format_id_list(
[node_set_field_name],
self.get_node_set_field_names(),
- 'node set field',
- single=True)
- [timestep] = self._format_id_list([timestep],
- self.get_timesteps(),
- 'timestep',
- single=True)
+ "node set field",
+ single=True,
+ )
+ [timestep] = self._format_id_list(
+ [timestep], self.get_timesteps(), "timestep", single=True
+ )
timestep_index = self._get_internal_timestep_index(timestep)
if not self.node_set_field_exists(node_set_field_name, node_set_id):
- self._missing_on_entity_error(node_set_field_name,
- 'node set field', node_set_id,
- 'node set')
+ self._missing_on_entity_error(
+ node_set_field_name, "node set field", node_set_id, "node set"
+ )
fields = self._get_node_set_fields(node_set_id)
return fields[node_set_field_name][timestep_index]
@@ -3264,7 +3583,8 @@ Source code for exomerge
"""
[element_block_id] = self._format_element_block_id_list(
- [element_block_id], single=True)
+ [element_block_id], single=True
+ )
return self.element_blocks[element_block_id][0]
[docs] def get_all_element_block_names(self):
@@ -3286,7 +3606,8 @@ Source code for exomerge
"""
return [
- x for x in self.get_element_block_ids()
+ x
+ for x in self.get_element_block_ids()
if self._is_standard_element_type(self._get_element_type(x))
]
@@ -3320,7 +3641,7 @@ Source code for exomerge
"""
return self._sort_field_names(list(self.node_fields.keys()))
-[docs] def get_node_set_field_names(self, node_set_ids='all'):
+[docs] def get_node_set_field_names(self, node_set_ids="all"):
"""
Return a list of all node set field names.
@@ -3339,7 +3660,7 @@ Source code for exomerge
names.update(list(self.node_sets[id_][-1].keys()))
return self._sort_field_names(list(names))
-[docs] def get_side_set_field_names(self, side_set_ids='all'):
+[docs] def get_side_set_field_names(self, side_set_ids="all"):
"""
Return a list of all side set field names.
@@ -3358,7 +3679,7 @@ Source code for exomerge
names.update(list(self._get_side_set_fields(id_).keys()))
return self._sort_field_names(list(names))
-[docs] def get_element_field_names(self, element_block_ids='all'):
+[docs] def get_element_field_names(self, element_block_ids="all"):
"""
Return a list of all element field names.
@@ -3371,8 +3692,7 @@ Source code for exomerge
>>> model.get_element_field_names(1)
"""
- element_block_ids = self._format_element_block_id_list(
- element_block_ids)
+ element_block_ids = self._format_element_block_id_list(element_block_ids)
names = set()
for id_ in element_block_ids:
names.update(list(self.element_blocks[id_][-1].keys()))
@@ -3400,14 +3720,12 @@ Source code for exomerge
def _get_internal_timestep_index(self, timestep):
"""Return the local timestep index."""
- [timestep] = self._format_id_list([timestep],
- self.get_timesteps(),
- 'timestep',
- single=True)
+ [timestep] = self._format_id_list(
+ [timestep], self.get_timesteps(), "timestep", single=True
+ )
return self.timesteps.index(timestep)
- def _create_element_field_truth_table(self, element_block_ids,
- field_names):
+ def _create_element_field_truth_table(self, element_block_ids, field_names):
"""
Return the element field truth table.
@@ -3438,7 +3756,8 @@ Source code for exomerge
# go through each case and set values to True if they exist
truth_table = [
self.side_set_field_exists(field_name, side_set_id)
- for side_set_id in side_set_ids for field_name in field_names
+ for side_set_id in side_set_ids
+ for field_name in field_names
]
return truth_table
@@ -3455,11 +3774,12 @@ Source code for exomerge
# go through each case and set values to True if they exist
truth_table = [
self.node_set_field_exists(field_name, node_set_id)
- for node_set_id in node_set_ids for field_name in field_names
+ for node_set_id in node_set_ids
+ for field_name in field_names
]
return truth_table
-[docs] def get_connectivity(self, element_block_id='auto'):
+[docs] def get_connectivity(self, element_block_id="auto"):
"""
Return the connectivity list of an element block.
@@ -3468,10 +3788,11 @@ Source code for exomerge
"""
[element_block_id] = self._format_element_block_id_list(
- [element_block_id], single=True)
+ [element_block_id], single=True
+ )
return self.element_blocks[element_block_id][2]
-[docs] def get_element_block_connectivity(self, element_block_id='auto'):
+[docs] def get_element_block_connectivity(self, element_block_id="auto"):
"""Alias for 'get_connectivity()'."""
return self.get_connectivity(element_block_id)
@@ -3484,21 +3805,22 @@ Source code for exomerge
>>> model.get_nodes_in_element_block([1, 3])
"""
- element_block_ids = self._format_element_block_id_list(
- element_block_ids)
+ element_block_ids = self._format_element_block_id_list(element_block_ids)
node_list = set()
for id_ in element_block_ids:
connectivity = self.get_connectivity(id_)
node_list.update(connectivity)
return sorted(node_list)
- def _rotate_nodes(self,
- axis,
- angle_in_degrees,
- node_indices='all',
- adjust_displacement_field='auto'):
+ def _rotate_nodes(
+ self,
+ axis,
+ angle_in_degrees,
+ node_indices="all",
+ adjust_displacement_field="auto",
+ ):
"""Rotate nodes about an axis by the given angle."""
- if adjust_displacement_field == 'auto':
+ if adjust_displacement_field == "auto":
adjust_displacement_field = self.displacement_field_exists()
# Create rotation matrix.
# x --> R * x
@@ -3522,38 +3844,51 @@ Source code for exomerge
rzy = uz * uy * (1 - cost) + ux * sint
rzz = cost + uz * uz * (1 - cost)
# Rotate nodes.
- if node_indices == 'all':
- self.nodes = [[
- rxx * x + rxy * y + rxz * z, ryx * x + ryy * y + ryz * z,
- rzx * x + rzy * y + rzz * z
- ] for x, y, z in self.nodes]
+ if node_indices == "all":
+ self.nodes = [
+ [
+ rxx * x + rxy * y + rxz * z,
+ ryx * x + ryy * y + ryz * z,
+ rzx * x + rzy * y + rzz * z,
+ ]
+ for x, y, z in self.nodes
+ ]
else:
for index in node_indices:
n = self.nodes[index]
self.nodes[index] = [
rxx * n[0] + rxy * n[1] + rxz * n[2],
ryx * n[0] + ryy * n[1] + ryz * n[2],
- rzx * n[0] + rzy * n[1] + rzz * n[2]
+ rzx * n[0] + rzy * n[1] + rzz * n[2],
]
# Rotate the displacement field.
if adjust_displacement_field:
(disp_x, disp_y, disp_z) = self._get_displacement_field_values()
for timestep_index in range(len(self.timesteps)):
- if node_indices == 'all':
+ if node_indices == "all":
new_disp_x = [
- rxx * x + rxy * y + rxz * z for x, y, z in zip(
- disp_x[timestep_index], disp_y[timestep_index],
- disp_z[timestep_index])
+ rxx * x + rxy * y + rxz * z
+ for x, y, z in zip(
+ disp_x[timestep_index],
+ disp_y[timestep_index],
+ disp_z[timestep_index],
+ )
]
new_disp_y = [
- ryx * x + ryy * y + ryz * z for x, y, z in zip(
- disp_x[timestep_index], disp_y[timestep_index],
- disp_z[timestep_index])
+ ryx * x + ryy * y + ryz * z
+ for x, y, z in zip(
+ disp_x[timestep_index],
+ disp_y[timestep_index],
+ disp_z[timestep_index],
+ )
]
new_disp_z = [
- rzx * x + rzy * y + rzz * z for x, y, z in zip(
- disp_x[timestep_index], disp_y[timestep_index],
- disp_z[timestep_index])
+ rzx * x + rzy * y + rzz * z
+ for x, y, z in zip(
+ disp_x[timestep_index],
+ disp_y[timestep_index],
+ disp_z[timestep_index],
+ )
]
disp_x[timestep_index] = new_disp_x
disp_y[timestep_index] = new_disp_y
@@ -3566,16 +3901,16 @@ Source code for exomerge
(x, y, z) = [
rxx * x + rxy * y + rxz * z,
ryx * x + ryy * y + ryz * z,
- rzx * x + rzy * y + rzz * z
+ rzx * x + rzy * y + rzz * z,
]
disp_x[timestep_index][index] = x
disp_y[timestep_index][index] = y
disp_z[timestep_index][index] = z
- def _translate_nodes(self, offset, node_indices='all'):
+ def _translate_nodes(self, offset, node_indices="all"):
"""Translate nodes by the given offset."""
(dx, dy, dz) = [float(x) for x in offset]
- if node_indices == 'all':
+ if node_indices == "all":
self.nodes = [[x + dx, y + dy, z + dz] for x, y, z in self.nodes]
else:
for index in node_indices:
@@ -3583,36 +3918,30 @@ Source code for exomerge
self.nodes[index][1] += dy
self.nodes[index][2] += dz
- def _scale_nodes(self,
- scale_factor,
- node_indices='all',
- adjust_displacement_field='auto'):
+ def _scale_nodes(
+ self, scale_factor, node_indices="all", adjust_displacement_field="auto"
+ ):
"""Scale nodes in the list by the given scale factor."""
scale_factor = float(scale_factor)
- if adjust_displacement_field == 'auto':
+ if adjust_displacement_field == "auto":
adjust_displacement_field = self.displacement_field_exists()
# Scale the nodal coordinates.
- if node_indices == 'all':
+ if node_indices == "all":
self.nodes = [[x * scale_factor for x in n] for n in self.nodes]
else:
for index in node_indices:
- self.nodes[index] = [
- x * scale_factor for x in self.nodes[index]
- ]
+ self.nodes[index] = [x * scale_factor for x in self.nodes[index]]
# Scale the displacement field.
if adjust_displacement_field:
for all_values in self._get_displacement_field_values():
for values in all_values:
- if node_indices == 'all':
+ if node_indices == "all":
values[:] = [x * scale_factor for x in values]
else:
for index in node_indices:
values[index] *= scale_factor
-[docs] def rotate_geometry(self,
- axis,
- angle_in_degrees,
- adjust_displacement_field='auto'):
+[docs] def rotate_geometry(self, axis, angle_in_degrees, adjust_displacement_field="auto"):
"""
Rotate the model about an axis by the given angle.
@@ -3623,9 +3952,9 @@ Source code for exomerge
>>> model.rotate_geometry([1, 0, 0], 90)
"""
- self._rotate_nodes(axis,
- angle_in_degrees,
- adjust_displacement_field=adjust_displacement_field)
+ self._rotate_nodes(
+ axis, angle_in_degrees, adjust_displacement_field=adjust_displacement_field
+ )
[docs] def translate_geometry(self, offset):
"""
@@ -3637,7 +3966,7 @@ Source code for exomerge
"""
self._translate_nodes(offset)
-[docs] def scale_geometry(self, scale_factor, adjust_displacement_field='auto'):
+[docs] def scale_geometry(self, scale_factor, adjust_displacement_field="auto"):
"""
Scale the model by the given factor.
@@ -3648,8 +3977,9 @@ Source code for exomerge
>>> model.scale_geometry(0.0254)
"""
- self._scale_nodes(scale_factor,
- adjust_displacement_field=adjust_displacement_field)
+ self._scale_nodes(
+ scale_factor, adjust_displacement_field=adjust_displacement_field
+ )
def _ensure_no_shared_nodes(self, element_block_ids):
"""
@@ -3659,34 +3989,33 @@ Source code for exomerge
other element block then an error message is output.
"""
- element_block_ids = self._format_element_block_id_list(
- element_block_ids)
+ element_block_ids = self._format_element_block_id_list(element_block_ids)
affected_nodes = self.get_nodes_in_element_block(element_block_ids)
nodes_in_other_blocks = self.get_nodes_in_element_block(
- list(set(self.get_element_block_ids()) - set(element_block_ids)))
+ list(set(self.get_element_block_ids()) - set(element_block_ids))
+ )
shared_nodes = sorted(
- set.intersection(set(affected_nodes), set(nodes_in_other_blocks)))
+ set.intersection(set(affected_nodes), set(nodes_in_other_blocks))
+ )
if shared_nodes:
max_nodes_to_display = 20
- node_list = ', '.join(
- [str(x) for x in shared_nodes[:max_nodes_to_display]])
+ node_list = ", ".join([str(x) for x in shared_nodes[:max_nodes_to_display]])
if len(shared_nodes) > max_nodes_to_display:
- node_list += ', ...'
+ node_list += ", ..."
self._error(
- 'Unable to operate on merged nodes.',
- 'You are attempting to operate on some element blocks '
- 'while keeping others unaffected. Because some nodes '
- 'are shared between the two groups, this cannot be '
- 'done. Use unmerge_element_blocks() to unmerge the '
- 'blocks if that is desired.\n'
- '\n'
- 'There are %d shared nodes: %s' %
- (len(shared_nodes), node_list))
-
-[docs] def translate_element_blocks(self,
- element_block_ids,
- offset,
- check_for_merged_nodes=True):
+ "Unable to operate on merged nodes.",
+ "You are attempting to operate on some element blocks "
+ "while keeping others unaffected. Because some nodes "
+ "are shared between the two groups, this cannot be "
+ "done. Use unmerge_element_blocks() to unmerge the "
+ "blocks if that is desired.\n"
+ "\n"
+ "There are %d shared nodes: %s" % (len(shared_nodes), node_list),
+ )
+
+[docs] def translate_element_blocks(
+ self, element_block_ids, offset, check_for_merged_nodes=True
+ ):
"""
Translate the specified element blocks by the given offset.
@@ -3694,19 +4023,20 @@ Source code for exomerge
>>> model.translate_element_blocks(1, [1.0, 2.0, 3.0])
"""
- element_block_ids = self._format_element_block_id_list(
- element_block_ids)
+ element_block_ids = self._format_element_block_id_list(element_block_ids)
if check_for_merged_nodes:
self._ensure_no_shared_nodes(element_block_ids)
affected_nodes = self.get_nodes_in_element_block(element_block_ids)
self._translate_nodes(offset, affected_nodes)
-[docs] def reflect_element_blocks(self,
- element_block_ids,
- point,
- normal,
- check_for_merged_nodes=True,
- adjust_displacement_field='auto'):
+[docs] def reflect_element_blocks(
+ self,
+ element_block_ids,
+ point,
+ normal,
+ check_for_merged_nodes=True,
+ adjust_displacement_field="auto",
+ ):
"""
Reflect the specified element blocks about the given plane.
@@ -3717,9 +4047,8 @@ Source code for exomerge
>>> model.reflect_element_blocks(1, [0, 0, 0], [1, 0, 0])
"""
- element_block_ids = self._format_element_block_id_list(
- element_block_ids)
- if adjust_displacement_field == 'auto':
+ element_block_ids = self._format_element_block_id_list(element_block_ids)
+ if adjust_displacement_field == "auto":
adjust_displacement_field = self.displacement_field_exists()
point = [float(x) for x in point]
scale = math.sqrt(sum(x * x for x in normal))
@@ -3729,8 +4058,8 @@ Source code for exomerge
affected_nodes = self.get_nodes_in_element_block(element_block_ids)
for index in affected_nodes:
distance = sum(
- (a - p) * n
- for a, p, n in zip(self.nodes[index], point, normal))
+ (a - p) * n for a, p, n in zip(self.nodes[index], point, normal)
+ )
self.nodes[index] = [
a - 2 * distance * n for a, n in zip(self.nodes[index], normal)
]
@@ -3752,11 +4081,13 @@ Source code for exomerge
# uninvert elements
self._invert_element_blocks(element_block_ids)
-[docs] def scale_element_blocks(self,
- element_block_ids,
- scale_factor,
- check_for_merged_nodes=True,
- adjust_displacement_field='auto'):
+[docs] def scale_element_blocks(
+ self,
+ element_block_ids,
+ scale_factor,
+ check_for_merged_nodes=True,
+ adjust_displacement_field="auto",
+ ):
"""
Scale all nodes in the given element blocks by the given amount.
@@ -3767,23 +4098,26 @@ Source code for exomerge
>>> model.scale_element_blocks(1, 0.0254)
"""
- element_block_ids = self._format_element_block_id_list(
- element_block_ids)
- if adjust_displacement_field == 'auto':
+ element_block_ids = self._format_element_block_id_list(element_block_ids)
+ if adjust_displacement_field == "auto":
adjust_displacement_field = self.displacement_field_exists()
if check_for_merged_nodes:
self._ensure_no_shared_nodes(element_block_ids)
affected_nodes = self.get_nodes_in_element_block(element_block_ids)
- self._scale_nodes(scale_factor,
- affected_nodes,
- adjust_displacement_field=adjust_displacement_field)
-
-[docs] def rotate_element_blocks(self,
- element_block_ids,
- axis,
- angle_in_degrees,
- check_for_merged_nodes=True,
- adjust_displacement_field='auto'):
+ self._scale_nodes(
+ scale_factor,
+ affected_nodes,
+ adjust_displacement_field=adjust_displacement_field,
+ )
+
+[docs] def rotate_element_blocks(
+ self,
+ element_block_ids,
+ axis,
+ angle_in_degrees,
+ check_for_merged_nodes=True,
+ adjust_displacement_field="auto",
+ ):
"""
Rotate all nodes in the given element blocks by the given amount.
@@ -3797,23 +4131,22 @@ Source code for exomerge
>>> model.rotate_element_blocks(1, [1, 0, 0], 90)
"""
- element_block_ids = self._format_element_block_id_list(
- element_block_ids)
- if adjust_displacement_field == 'auto':
+ element_block_ids = self._format_element_block_id_list(element_block_ids)
+ if adjust_displacement_field == "auto":
adjust_displacement_field = self.displacement_field_exists()
if check_for_merged_nodes:
self._ensure_no_shared_nodes(element_block_ids)
affected_nodes = self.get_nodes_in_element_block(element_block_ids)
- self._rotate_nodes(axis,
- angle_in_degrees,
- affected_nodes,
- adjust_displacement_field=adjust_displacement_field)
+ self._rotate_nodes(
+ axis,
+ angle_in_degrees,
+ affected_nodes,
+ adjust_displacement_field=adjust_displacement_field,
+ )
-[docs] def displace_element_blocks(self,
- element_block_ids,
- offset,
- timesteps='all',
- check_for_merged_nodes=True):
+[docs] def displace_element_blocks(
+ self, element_block_ids, offset, timesteps="all", check_for_merged_nodes=True
+ ):
"""
Displace all nodes in the given element blocks.
@@ -3826,10 +4159,8 @@ Source code for exomerge
>>> model.displace_element_blocks('all', [1.0, 2.0, 3.0])
"""
- element_block_ids = self._format_element_block_id_list(
- element_block_ids)
- timesteps = self._format_id_list(timesteps, self.get_timesteps(),
- 'timestep')
+ element_block_ids = self._format_element_block_id_list(element_block_ids)
+ timesteps = self._format_id_list(timesteps, self.get_timesteps(), "timestep")
if check_for_merged_nodes:
self._ensure_no_shared_nodes(element_block_ids)
timestep_indices = [self.timesteps.index(x) for x in timesteps]
@@ -3837,10 +4168,11 @@ Source code for exomerge
# if no timesteps exist, issue an error
if not self.timesteps:
self._error(
- 'No timesteps defined',
- 'A displacement field cannot exist if no timesteps '
- 'are defined. To avoid this error, create a timestep '
- 'before calling this function.')
+ "No timesteps defined",
+ "A displacement field cannot exist if no timesteps "
+ "are defined. To avoid this error, create a timestep "
+ "before calling this function.",
+ )
# get displacement field indices
displacement_fields = self._get_displacement_field_values()
# get affected nodes
@@ -3852,39 +4184,46 @@ Source code for exomerge
for index in node_list:
values[index] += offset[dimension]
- def _rename_field_on_entity(self, field_type, field_name, new_field_name,
- field_name_list_function, entity_type,
- entity_list, entity_list_function,
- entity_objects):
+ def _rename_field_on_entity(
+ self,
+ field_type,
+ field_name,
+ new_field_name,
+ field_name_list_function,
+ entity_type,
+ entity_list,
+ entity_list_function,
+ entity_objects,
+ ):
"""Rename a field defined on an entity."""
- entity_list = self._format_id_list(entity_list, entity_list_function(),
- entity_type)
+ entity_list = self._format_id_list(
+ entity_list, entity_list_function(), entity_type
+ )
[field_name] = self._format_id_list(
- [field_name],
- field_name_list_function(entity_list),
- field_type,
- single=True)
+ [field_name], field_name_list_function(entity_list), field_type, single=True
+ )
for id_ in entity_list:
fields = entity_objects[id_][-1]
if field_name not in fields:
self._warning(
- field_type + ' not defined.', 'The given %s "%s" is not '
- 'defined on %s %s. It cannot '
- 'be renamed.' %
- (field_type, field_name, entity_type, str(id_)))
+ field_type + " not defined.",
+ 'The given %s "%s" is not '
+ "defined on %s %s. It cannot "
+ "be renamed." % (field_type, field_name, entity_type, str(id_)),
+ )
continue
if field_name == new_field_name:
continue
if new_field_name in fields:
- self._exists_on_entity_warning(new_field_name, field_type, id_,
- entity_type)
+ self._exists_on_entity_warning(
+ new_field_name, field_type, id_, entity_type
+ )
fields[new_field_name] = fields[field_name]
del fields[field_name]
-[docs] def rename_element_field(self,
- element_field_name,
- new_element_field_name,
- element_block_ids='all'):
+[docs] def rename_element_field(
+ self, element_field_name, new_element_field_name, element_block_ids="all"
+ ):
"""
Rename an element field.
@@ -3892,17 +4231,20 @@ Source code for exomerge
>>> model.rename_element_field('p', 'pressure')
"""
- self._rename_field_on_entity('element field', element_field_name,
- new_element_field_name,
- self.get_element_field_names,
- 'element block', element_block_ids,
- self.get_element_block_ids,
- self.element_blocks)
+ self._rename_field_on_entity(
+ "element field",
+ element_field_name,
+ new_element_field_name,
+ self.get_element_field_names,
+ "element block",
+ element_block_ids,
+ self.get_element_block_ids,
+ self.element_blocks,
+ )
-[docs] def rename_side_set_field(self,
- side_set_field_name,
- new_side_set_field_name,
- side_set_ids='all'):
+[docs] def rename_side_set_field(
+ self, side_set_field_name, new_side_set_field_name, side_set_ids="all"
+ ):
"""
Rename a side set field.
@@ -3910,11 +4252,16 @@ Source code for exomerge
>>> model.rename_side_set_field('cp', 'contact_pressure')
"""
- self._rename_field_on_entity('side set field', side_set_field_name,
- new_side_set_field_name,
- self.get_side_set_field_names, 'side set',
- side_set_ids, self.get_side_set_ids,
- self.side_sets)
+ self._rename_field_on_entity(
+ "side set field",
+ side_set_field_name,
+ new_side_set_field_name,
+ self.get_side_set_field_names,
+ "side set",
+ side_set_ids,
+ self.get_side_set_ids,
+ self.side_sets,
+ )
[docs] def get_side_set_name(self, side_set_id):
"""Return the name of a side set."""
@@ -3935,10 +4282,9 @@ Source code for exomerge
[side_set_id] = self._format_side_set_id_list([side_set_id], single=True)
return self.side_sets[side_set_id][-1]
-[docs] def rename_node_set_field(self,
- node_set_field_name,
- new_node_set_field_name,
- node_set_ids='all'):
+[docs] def rename_node_set_field(
+ self, node_set_field_name, new_node_set_field_name, node_set_ids="all"
+ ):
"""
Rename a node set field.
@@ -3946,19 +4292,29 @@ Source code for exomerge
>>> model.rename_node_set_field('cp', 'contact_pressure')
"""
- self._rename_field_on_entity('node set field', node_set_field_name,
- new_node_set_field_name,
- self.get_node_set_field_names, 'node set',
- node_set_ids, self.get_node_set_ids,
- self.node_sets)
-
- def _rename_entity(self, entity_type, entity_name, new_entity_name,
- entity_name_list_function, entity_objects):
+ self._rename_field_on_entity(
+ "node set field",
+ node_set_field_name,
+ new_node_set_field_name,
+ self.get_node_set_field_names,
+ "node set",
+ node_set_ids,
+ self.get_node_set_ids,
+ self.node_sets,
+ )
+
+ def _rename_entity(
+ self,
+ entity_type,
+ entity_name,
+ new_entity_name,
+ entity_name_list_function,
+ entity_objects,
+ ):
"""Rename an entity."""
- [entity_name] = self._format_id_list([entity_name],
- entity_name_list_function(),
- entity_type,
- single=True)
+ [entity_name] = self._format_id_list(
+ [entity_name], entity_name_list_function(), entity_type, single=True
+ )
if new_entity_name == entity_name:
return
if new_entity_name in entity_name_list_function():
@@ -3974,11 +4330,15 @@ Source code for exomerge
>>> model.rename_node_field('temp', 'temperature')
"""
- self._rename_entity('node field', node_field_name, new_node_field_name,
- self.get_node_field_names, self.node_fields)
+ self._rename_entity(
+ "node field",
+ node_field_name,
+ new_node_field_name,
+ self.get_node_field_names,
+ self.node_fields,
+ )
-[docs] def rename_global_variable(self, global_variable_name,
- new_global_variable_name):
+[docs] def rename_global_variable(self, global_variable_name, new_global_variable_name):
"""
Rename a global variable.
@@ -3986,10 +4346,13 @@ Source code for exomerge
>>> model.rename_global_variable('ke', 'kinetic_energy')
"""
- self._rename_entity('global variable', global_variable_name,
- new_global_variable_name,
- self.get_global_variable_names,
- self.global_variables)
+ self._rename_entity(
+ "global variable",
+ global_variable_name,
+ new_global_variable_name,
+ self.get_global_variable_names,
+ self.global_variables,
+ )
[docs] def rename_element_block(self, element_block_id, new_element_block_id):
"""
@@ -4005,25 +4368,28 @@ Source code for exomerge
"""
[element_block_id] = self._format_element_block_id_list(
- [element_block_id], single=True)
+ [element_block_id], single=True
+ )
# if we're just changing the name
if isinstance(new_element_block_id, str):
# if the same name already, just exit
- if (self.element_blocks[element_block_id][0] ==
- new_element_block_id):
+ if self.element_blocks[element_block_id][0] == new_element_block_id:
return
# if the name already exists, issue a warning
if self.element_block_exists(new_element_block_id):
- self._exists_warning('"' + new_element_block_id + '"',
- 'element block')
+ self._exists_warning('"' + new_element_block_id + '"', "element block")
# rename it
self.element_blocks[element_block_id][0] = new_element_block_id
return
assert isinstance(new_element_block_id, int)
# rename the block
- self._rename_entity('element block', element_block_id,
- new_element_block_id, self.get_element_block_ids,
- self.element_blocks)
+ self._rename_entity(
+ "element block",
+ element_block_id,
+ new_element_block_id,
+ self.get_element_block_ids,
+ self.element_blocks,
+ )
# adjust side sets
for side_set_id in self.get_side_set_ids():
members = self.get_side_set_members(side_set_id)
@@ -4057,13 +4423,18 @@ Source code for exomerge
return
# if the name already exists, issue a warning
if self.node_set_exists(new_node_set_id):
- self._exists_warning('"' + new_node_set_id + '"', 'node set')
+ self._exists_warning('"' + new_node_set_id + '"', "node set")
# rename it
self.node_sets[node_set_id][0] = new_node_set_id
return
# rename it
- self._rename_entity('node set', node_set_id, new_node_set_id,
- self.get_node_set_ids, self.node_sets)
+ self._rename_entity(
+ "node set",
+ node_set_id,
+ new_node_set_id,
+ self.get_node_set_ids,
+ self.node_sets,
+ )
[docs] def rename_side_set(self, side_set_id, new_side_set_id):
"""
@@ -4086,31 +4457,36 @@ Source code for exomerge
return
# if the name already exists, issue a warning
if self.side_set_exists(new_side_set_id):
- self._exists_warning('"' + new_side_set_id + '"', 'side set')
+ self._exists_warning('"' + new_side_set_id + '"', "side set")
# rename it
self.side_sets[side_set_id][0] = new_side_set_id
return
- self._rename_entity('side set', side_set_id, new_side_set_id,
- self.get_side_set_ids, self.side_sets)
+ self._rename_entity(
+ "side set",
+ side_set_id,
+ new_side_set_id,
+ self.get_side_set_ids,
+ self.side_sets,
+ )
def _empty_field_warning(self):
"""Issue a warning if no timesteps exist."""
assert not self.get_timesteps()
self._warning(
- 'Creating an empty field',
- 'No timesteps are defined. Because fields are only '
- 'defined at each timestep, creating a field when no '
- 'timesteps are defined will allow let the field to '
- 'have any values. By default, empty fields are not '
- 'exported.\n'
- '\n'
- 'To avoid this warning, create a timestep before '
- 'creating a field.')
-
-[docs] def create_element_field(self,
- element_field_name,
- element_block_ids='all',
- value='auto'):
+ "Creating an empty field",
+ "No timesteps are defined. Because fields are only "
+ "defined at each timestep, creating a field when no "
+ "timesteps are defined will allow let the field to "
+ "have any values. By default, empty fields are not "
+ "exported.\n"
+ "\n"
+ "To avoid this warning, create a timestep before "
+ "creating a field.",
+ )
+
+[docs] def create_element_field(
+ self, element_field_name, element_block_ids="all", value="auto"
+ ):
"""
Create an element field on one or more element blocks.
@@ -4126,19 +4502,20 @@ Source code for exomerge
if not self.get_timesteps():
self._empty_field_warning()
# get list of block ids
- element_block_ids = self._format_element_block_id_list(
- element_block_ids)
+ element_block_ids = self._format_element_block_id_list(element_block_ids)
# get the value to assign
- if value == 'auto':
+ if value == "auto":
value = self._get_default_field_value(element_field_name)
# for each block
for element_block_id in element_block_ids:
# if it exists, no need to do anything
if self.element_field_exists(element_field_name, element_block_id):
- self._exists_on_entity_warning(element_field_name,
- 'element field',
- element_block_id,
- 'element block')
+ self._exists_on_entity_warning(
+ element_field_name,
+ "element field",
+ element_block_id,
+ "element block",
+ )
# get the element block info
element_count = self.get_element_count(element_block_id)
# create an empty field
@@ -4149,7 +4526,7 @@ Source code for exomerge
fields = self._get_element_block_fields(element_block_id)
fields[element_field_name] = values
-[docs] def create_node_field(self, node_field_name, value='auto'):
+[docs] def create_node_field(self, node_field_name, value="auto"):
"""
Create a node field and assign it a default value.
@@ -4166,10 +4543,10 @@ Source code for exomerge
self._empty_field_warning()
# if it exists, no need to do anything
if self.node_field_exists(node_field_name):
- self._exists_warning(node_field_name, 'node field')
+ self._exists_warning(node_field_name, "node field")
return
# get the value
- if value == 'auto':
+ if value == "auto":
value = self._get_default_field_value(node_field_name)
# create the new field
new_field_values = []
@@ -4177,10 +4554,9 @@ Source code for exomerge
new_field_values.append([value] * len(self.nodes))
self.node_fields[node_field_name] = new_field_values
-[docs] def create_node_set_field(self,
- node_set_field_name,
- node_set_ids='all',
- value='auto'):
+[docs] def create_node_set_field(
+ self, node_set_field_name, node_set_ids="all", value="auto"
+ ):
"""
Create a node set field on the given node sets.
@@ -4193,7 +4569,7 @@ Source code for exomerge
"""
node_set_ids = self._format_node_set_id_list(node_set_ids)
- if value == 'auto':
+ if value == "auto":
value = self._get_default_field_value(node_set_field_name)
for node_set_id in node_set_ids:
members = self.get_node_set_members(node_set_id)
@@ -4201,19 +4577,18 @@ Source code for exomerge
member_count = len(members)
# if it exists, warn about overwriting
if self.node_set_field_exists(node_set_field_name, [node_set_id]):
- self._exists_on_entity_warning(node_set_field_name,
- 'node set field', node_set_id,
- 'node set')
+ self._exists_on_entity_warning(
+ node_set_field_name, "node set field", node_set_id, "node set"
+ )
# create the new field
new_field_values = []
for _ in range(len(self.timesteps)):
new_field_values.append([value] * member_count)
fields[node_set_field_name] = new_field_values
-[docs] def create_side_set_field(self,
- side_set_field_name,
- side_set_ids='all',
- value='auto'):
+[docs] def create_side_set_field(
+ self, side_set_field_name, side_set_ids="all", value="auto"
+ ):
"""
Create a side set field.
@@ -4228,7 +4603,7 @@ Source code for exomerge
"""
side_set_ids = self._format_side_set_id_list(side_set_ids)
- if value == 'auto':
+ if value == "auto":
value = self._get_default_field_value(side_set_field_name)
for side_set_id in side_set_ids:
members = self.get_side_set_members(side_set_id)
@@ -4236,9 +4611,9 @@ Source code for exomerge
member_count = len(members)
# if it exists, warn about overwriting
if self.side_set_field_exists(side_set_field_name, side_set_id):
- self._exists_on_entity_warning(side_set_field_name,
- 'side set field', side_set_id,
- 'side set')
+ self._exists_on_entity_warning(
+ side_set_field_name, "side set field", side_set_id, "side set"
+ )
# create the new field
new_field_values = []
for _ in range(len(self.timesteps)):
@@ -4304,21 +4679,21 @@ Source code for exomerge