├── tests ├── test_data │ ├── __init__.py │ └── element_results.py ├── test_model.py ├── abaqus │ ├── input │ │ ├── tri_CPE3.inp │ │ ├── tri_CPE3H.inp │ │ ├── tri_CPS3.inp │ │ ├── quad_CPE4.inp │ │ ├── quad_CPS4.inp │ │ ├── templates │ │ │ ├── elem_tri.inp │ │ │ ├── elem_quad.inp │ │ │ └── elem_hex.inp │ │ ├── quad_CPE4H.inp │ │ ├── quad_CPS4I.inp │ │ ├── quad_CPS4R.inp │ │ ├── hex_C3D8.inp │ │ └── discontinuous_numbering_2D.inp │ ├── fil │ │ ├── tri_CPE3.fil │ │ ├── tri_CPS3.fil │ │ ├── tri_CPE3H.fil │ │ ├── quad_CPS4R.fil │ │ ├── quad_CPS4.fil │ │ ├── quad_CPS4I.fil │ │ ├── quad_CPE4.fil │ │ ├── quad_CPE4H.fil │ │ ├── discontinuous_numbering_2D.fil │ │ └── hex_C3D8.fil │ └── Makefile ├── test_elements.py └── test_reader.py ├── src └── pybaqus │ ├── __init__.py │ ├── step.py │ ├── reader.py │ ├── nodes.py │ ├── faces.py │ ├── elements.py │ ├── model.py │ └── fil_result.py ├── .gitignore ├── examples ├── mesh_hole.png ├── mesh_results.png └── Displacement_visualization │ ├── displacement_visualization.py │ ├── model.inp │ └── model_results.fil ├── CITATION.cff ├── pyproject.toml ├── LICENSE ├── contrib └── modify_abaqus_inp.py ├── .github └── workflows │ └── python-publish.yml └── README.md /tests/test_data/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/pybaqus/__init__.py: -------------------------------------------------------------------------------- 1 | __version__ = '0.1.0' 2 | 3 | from .reader import open_fil 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | poetry.lock 2 | build/ 3 | dist/ 4 | *.rpy 5 | *.egg-info 6 | __pycache__/ 7 | -------------------------------------------------------------------------------- /examples/mesh_hole.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cristobaltapia/pybaqus/HEAD/examples/mesh_hole.png -------------------------------------------------------------------------------- /examples/mesh_results.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cristobaltapia/pybaqus/HEAD/examples/mesh_results.png -------------------------------------------------------------------------------- /CITATION.cff: -------------------------------------------------------------------------------- 1 | cff-version: 1.2.0 2 | authors: 3 | - family-names: "Tapia Camú" 4 | given-names: "Cristóbal" 5 | orcid: "https://orcid.org/0000-0003-2228-1686" 6 | title: "Pybaqus: A Python library for the visualization and post-processing of Abaqus ASCII result files" 7 | version: 0.2.9 8 | url: "https://github.com/cristobaltapia/pybaqus" 9 | -------------------------------------------------------------------------------- /examples/Displacement_visualization/displacement_visualization.py: -------------------------------------------------------------------------------- 1 | from pybaqus import open_fil 2 | import pyvista as pv 3 | 4 | res = open_fil("model_results.fil") 5 | 6 | mesh = res.get_deformed_mesh(step=1, inc=1, scale=3) 7 | U1 = res.get_nodal_result(var="U1", step=1, inc=1) 8 | mesh.point_arrays["U1"] = U1 9 | 10 | 11 | plot = pv.Plotter() 12 | plot.add_mesh(mesh, show_edges=True, scalars="U1", show_scalar_bar=True) 13 | plot.view_xy() 14 | plot.show() 15 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "pybaqus" 3 | version = "0.2.16" 4 | description = "A Python library for the visualization and post-processing of Abaqus ASCII result files" 5 | readme = "README.md" 6 | authors = [ 7 | { name = "Cristóbal Tapia Camú", email = "crtapia@gmail.com" } 8 | ] 9 | requires-python = ">=3.10" 10 | dependencies = [ 11 | "numpy>=2.1.2", 12 | "pyvista>=0.44.1", 13 | "scipy>=1.14.1", 14 | "tqdm>=4.66.5", 15 | "vtk>=9.3.1", 16 | ] 17 | 18 | [build-system] 19 | requires = ["hatchling"] 20 | build-backend = "hatchling.build" 21 | 22 | [tool.uv] 23 | dev-dependencies = [ 24 | "pytest>=8.3.3", 25 | ] 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Cristóbal Tapia Camú 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/pybaqus/step.py: -------------------------------------------------------------------------------- 1 | """ 2 | Define a step object 3 | """ 4 | import numpy as np 5 | 6 | class Step(object): 7 | 8 | """Class to contain step information and methods 9 | 10 | Parameters 11 | ---------- 12 | model : TODO 13 | n : int 14 | data : dict 15 | 16 | """ 17 | 18 | def __init__(self, model, n, data): 19 | """TODO: to be defined. 20 | 21 | 22 | """ 23 | self._model = model 24 | self._n = n 25 | self._data = data 26 | self.tot_time = data["total time"] 27 | self.max_creep = data["max creep"] 28 | self.sol_apl = data["solution amplitude"] 29 | self.proc_type = data["procedure type"] 30 | self.step_n = data["step number"] 31 | self.lin_pert = data["linear perturbation"] 32 | self.freq = data["frequency"] 33 | self.subheading = data["subheading"] 34 | 35 | self.step_time: list = [data["step time"]] 36 | self.load_prop: list = [data["load proportionality"]] 37 | self.time_inc: list = [data["time increment"]] 38 | self.increments: list = [data["increment number"]] 39 | 40 | def add_increment(self, inc, time_inc, step_time, load_prop): 41 | """Add increment to the step object 42 | 43 | Parameters 44 | ---------- 45 | inc : TODO 46 | 47 | """ 48 | self.step_time.append(step_time) 49 | self.load_prop.append(load_prop) 50 | self.increments.append(inc) 51 | self.time_inc.append(time_inc) 52 | 53 | return 1 54 | -------------------------------------------------------------------------------- /src/pybaqus/reader.py: -------------------------------------------------------------------------------- 1 | """ 2 | Utilities to read the ASCII *.fil files generates by abaqus. 3 | """ 4 | 5 | import re 6 | 7 | from pybaqus.fil_result import FilParser 8 | 9 | 10 | def open_fil(file_name, progress=False): 11 | """Read the *.fil file 12 | 13 | Parameters 14 | ---------- 15 | file_name : str 16 | Path to the *.fil file 17 | progress : bool 18 | Indicates whether the progress of the reading process should be shown 19 | in a progress bar. (default: False) 20 | 21 | Returns 22 | ------- 23 | Result : Object containing the results of the *.fil file 24 | 25 | """ 26 | try: 27 | if progress: 28 | print("Reading records...") 29 | 30 | records = read_records(file_name) 31 | 32 | # Create result object 33 | if progress: 34 | print("Parsing records...") 35 | 36 | result = FilParser(records, progress=progress) 37 | del records 38 | 39 | return result.model 40 | 41 | except FileNotFoundError as e: 42 | raise e 43 | except Exception as e: 44 | raise e 45 | 46 | 47 | def read_records(file_name: str): 48 | with open(file_name, "r") as result: 49 | content = result.read().replace("\n", "") 50 | # Make a list with each record. 51 | # Each record starts with `*`, so we just need to use a regex to return each 52 | # record. 53 | pattern = r"(?<=\*)+.+?(?=\*)|(?<=\*)+.+?(?=$)" 54 | records = re.findall(pattern, content) 55 | del content 56 | 57 | return records 58 | -------------------------------------------------------------------------------- /tests/test_model.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from pybaqus.model import Model 3 | from pybaqus.nodes import Node2D, Node3D 4 | 5 | @pytest.fixture 6 | def empty_model(): 7 | return Model() 8 | 9 | # @pytest.fixture 10 | # def new_2D_node(): 11 | # return Node2D(1, dof_map=[]) 12 | 13 | def test_model_initialization(empty_model): 14 | assert isinstance(empty_model, Model) 15 | assert len(empty_model.nodes) == 0 16 | assert len(empty_model.elements) == 0 17 | assert len(empty_model.element_sets) == 0 18 | assert len(empty_model.node_sets) == 0 19 | assert len(empty_model.surfaces) == 0 20 | 21 | def test_add_node(empty_model): 22 | class MockNode: 23 | def __init__(self, num): 24 | self._num = num 25 | 26 | node = MockNode(1) 27 | empty_model.add_node(node) 28 | assert len(empty_model.nodes) == 1 29 | assert empty_model.nodes[1] == node 30 | 31 | def test_add_element(empty_model): 32 | class MockElement: 33 | def __init__(self, num): 34 | self.num = num 35 | 36 | element = MockElement(1) 37 | empty_model.add_element(element) 38 | assert len(empty_model.elements) == 1 39 | assert empty_model.elements[1] == element 40 | 41 | def test_add_set(empty_model): 42 | elements = [1, 2, 3] 43 | result = empty_model.add_set("test_set", elements, "element") 44 | assert "test_set" in empty_model.element_sets 45 | assert empty_model.element_sets["test_set"] == elements 46 | assert result == elements 47 | 48 | nodes = [4, 5, 6] 49 | result = empty_model.add_set("test_node_set", nodes, "node") 50 | assert "test_node_set" in empty_model.node_sets 51 | assert empty_model.node_sets["test_node_set"] == nodes 52 | assert result == nodes 53 | 54 | -------------------------------------------------------------------------------- /contrib/modify_abaqus_inp.py: -------------------------------------------------------------------------------- 1 | """ 2 | This file contains a utility function to generate and modify the Abaqus 3 | input file (*.inp) so that the results are written in the ASCII output 4 | format (*.fil). 5 | 6 | Author: Cristóbal Tapia Camú 7 | E-mail: crtapia@gmail.com 8 | """ 9 | 10 | 11 | def get_ascii_job(job_obj): 12 | """Configure Job to save results in the ASCII format (*.fil). 13 | 14 | Parameters 15 | ---------- 16 | job_obj : TODO 17 | 18 | """ 19 | job_obj.writeInput(consistencyChecking=False) 20 | 21 | input_lines = ("*FILE FORMAT, ASCII\n" + "*EL FILE\n" + "S, E, COORD\n" + 22 | "*NODE FILE\n" + "COORD, U\n") 23 | 24 | # Open *inp file 25 | file_name = job_obj.name + ".inp" 26 | 27 | with open(file_name, "r") as inp_file: 28 | lines = inp_file.readlines() 29 | 30 | with open(file_name, "w") as inp_file: 31 | for l in lines: 32 | if l == "*End Step\n": 33 | inp_file.writelines(input_lines) 34 | inp_file.write(l) 35 | else: 36 | inp_file.write(l) 37 | 38 | job_ascii = mdb.JobFromInputFile(name=job_obj.name, inputFileName=job_obj.name + ".inp", 39 | type=ANALYSIS, memory=90, memoryUnits=PERCENTAGE, 40 | getMemoryFromAnalysis=True, explicitPrecision=SINGLE, 41 | nodalOutputPrecision=SINGLE, 42 | userSubroutine=job_obj.userSubroutine, 43 | scratch=job_obj.scratch, multiprocessingMode=DEFAULT, 44 | numCpus=job_obj.numCpus, numDomains=job_obj.numDomains) 45 | 46 | return job_ascii 47 | -------------------------------------------------------------------------------- /tests/abaqus/input/tri_CPE3.inp: -------------------------------------------------------------------------------- 1 | *Heading 2 | Test elements of the type CPE3 with triangular shape 3 | *Preprint, echo=NO, model=NO, history=NO, contact=NO 4 | ** 5 | ** PARTS 6 | ** 7 | *Part, name=test_part 8 | *End Part 9 | ** 10 | ** 11 | ** ASSEMBLY 12 | ** 13 | *Assembly, name=Assembly 14 | ** 15 | *Instance, name=test_instance, part=test_part 16 | *Node 17 | 1, 0.1, 0.2 18 | 2, 12.9, 0.2 19 | 3, 0.1, 10.5 20 | *Element, type=CPE3 21 | 1, 1, 2, 3 22 | *Nset, nset=set-test_part, generate 23 | 1, 3, 1 24 | *Elset, elset=set-test_part 25 | 1, 26 | ** Section: test-section 27 | *Solid Section, elset=set-test_part, material=test-material 28 | 0.1, 29 | *End Instance 30 | ** 31 | *Nset, nset=set_load, internal, instance=test_instance 32 | 3 33 | *Nset, nset=set_bc_1, internal, instance=test_instance 34 | 1, 35 | *Nset, nset=set_bc_2, internal, instance=test_instance 36 | 2, 37 | *End Assembly 38 | ** 39 | ** MATERIALS 40 | ** 41 | *Material, name=test-material 42 | *Elastic 43 | 1e05, 0.25 44 | ** 45 | ** BOUNDARY CONDITIONS 46 | ** 47 | ** Name: test-bc-1 Type: Displacement/Rotation 48 | *Boundary 49 | set_bc_1, 1, 1 50 | set_bc_1, 2, 2 51 | ** Name: test-bc-2 Type: Displacement/Rotation 52 | *Boundary 53 | set_bc_2, 2, 2 54 | ** ---------------------------------------------------------------- 55 | ** 56 | ** STEP: test-step 57 | ** 58 | *Step, name=test-step, nlgeom=NO, inc=10 59 | *Static 60 | 1., 1., 1e-05, 1. 61 | ** 62 | ** LOADS 63 | ** 64 | ** Name: test-load Type: Concentrated force 65 | *Cload 66 | set_load, 2, 1e03 67 | ** 68 | ** OUTPUT REQUESTS 69 | ** 70 | *Restart, write, frequency=0 71 | ** 72 | ** FIELD OUTPUT: F-Output-1 73 | ** 74 | *Output, field, variable=PRESELECT 75 | ** 76 | ** HISTORY OUTPUT: H-Output-1 77 | ** 78 | *Output, history, variable=PRESELECT 79 | ** 80 | ** Output to ASCII-file 81 | ** 82 | *FILE FORMAT, ASCII 83 | ** 84 | *EL FILE 85 | S, E, COORD 86 | ** 87 | *NODE FILE 88 | COORD, U 89 | ** 90 | *End Step 91 | -------------------------------------------------------------------------------- /tests/abaqus/input/tri_CPE3H.inp: -------------------------------------------------------------------------------- 1 | *Heading 2 | Test elements of the type CPE3H with triangular shape 3 | *Preprint, echo=NO, model=NO, history=NO, contact=NO 4 | ** 5 | ** PARTS 6 | ** 7 | *Part, name=test_part 8 | *End Part 9 | ** 10 | ** 11 | ** ASSEMBLY 12 | ** 13 | *Assembly, name=Assembly 14 | ** 15 | *Instance, name=test_instance, part=test_part 16 | *Node 17 | 1, 0.1, 0.2 18 | 2, 12.9, 0.2 19 | 3, 0.1, 10.5 20 | *Element, type=CPE3H 21 | 1, 1, 2, 3 22 | *Nset, nset=set-test_part, generate 23 | 1, 3, 1 24 | *Elset, elset=set-test_part 25 | 1, 26 | ** Section: test-section 27 | *Solid Section, elset=set-test_part, material=test-material 28 | 0.1, 29 | *End Instance 30 | ** 31 | *Nset, nset=set_load, internal, instance=test_instance 32 | 3 33 | *Nset, nset=set_bc_1, internal, instance=test_instance 34 | 1, 35 | *Nset, nset=set_bc_2, internal, instance=test_instance 36 | 2, 37 | *End Assembly 38 | ** 39 | ** MATERIALS 40 | ** 41 | *Material, name=test-material 42 | *Elastic 43 | 1e05, 0.25 44 | ** 45 | ** BOUNDARY CONDITIONS 46 | ** 47 | ** Name: test-bc-1 Type: Displacement/Rotation 48 | *Boundary 49 | set_bc_1, 1, 1 50 | set_bc_1, 2, 2 51 | ** Name: test-bc-2 Type: Displacement/Rotation 52 | *Boundary 53 | set_bc_2, 2, 2 54 | ** ---------------------------------------------------------------- 55 | ** 56 | ** STEP: test-step 57 | ** 58 | *Step, name=test-step, nlgeom=NO, inc=10 59 | *Static 60 | 1., 1., 1e-05, 1. 61 | ** 62 | ** LOADS 63 | ** 64 | ** Name: test-load Type: Concentrated force 65 | *Cload 66 | set_load, 2, 1e03 67 | ** 68 | ** OUTPUT REQUESTS 69 | ** 70 | *Restart, write, frequency=0 71 | ** 72 | ** FIELD OUTPUT: F-Output-1 73 | ** 74 | *Output, field, variable=PRESELECT 75 | ** 76 | ** HISTORY OUTPUT: H-Output-1 77 | ** 78 | *Output, history, variable=PRESELECT 79 | ** 80 | ** Output to ASCII-file 81 | ** 82 | *FILE FORMAT, ASCII 83 | ** 84 | *EL FILE 85 | S, E, COORD 86 | ** 87 | *NODE FILE 88 | COORD, U 89 | ** 90 | *End Step 91 | -------------------------------------------------------------------------------- /tests/abaqus/input/tri_CPS3.inp: -------------------------------------------------------------------------------- 1 | *Heading 2 | Test elements of the type CPS3 with triangular shape 3 | *Preprint, echo=NO, model=NO, history=NO, contact=NO 4 | ** 5 | ** PARTS 6 | ** 7 | *Part, name=test_part 8 | *End Part 9 | ** 10 | ** 11 | ** ASSEMBLY 12 | ** 13 | *Assembly, name=Assembly 14 | ** 15 | *Instance, name=test_instance, part=test_part 16 | *Node 17 | 1, 0.1, 0.2 18 | 2, 12.9, 0.2 19 | 3, 0.1, 10.5 20 | *Element, type=CPS3 21 | 1, 1, 2, 3 22 | *Nset, nset=set-test_part, generate 23 | 1, 3, 1 24 | *Elset, elset=set-test_part 25 | 1, 26 | ** Section: test-section 27 | *Solid Section, elset=set-test_part, material=test-material 28 | 0.1, 29 | *End Instance 30 | ** 31 | *Nset, nset=set_load, internal, instance=test_instance 32 | 3 33 | *Nset, nset=set_bc_1, internal, instance=test_instance 34 | 1, 35 | *Nset, nset=set_bc_2, internal, instance=test_instance 36 | 2, 37 | *End Assembly 38 | ** 39 | ** MATERIALS 40 | ** 41 | *Material, name=test-material 42 | *Elastic 43 | 1e05, 0.25 44 | ** 45 | ** BOUNDARY CONDITIONS 46 | ** 47 | ** Name: test-bc-1 Type: Displacement/Rotation 48 | *Boundary 49 | set_bc_1, 1, 1 50 | set_bc_1, 2, 2 51 | ** Name: test-bc-2 Type: Displacement/Rotation 52 | *Boundary 53 | set_bc_2, 2, 2 54 | ** ---------------------------------------------------------------- 55 | ** 56 | ** STEP: test-step 57 | ** 58 | *Step, name=test-step, nlgeom=NO, inc=10 59 | *Static 60 | 1., 1., 1e-05, 1. 61 | ** 62 | ** LOADS 63 | ** 64 | ** Name: test-load Type: Concentrated force 65 | *Cload 66 | set_load, 2, 1e03 67 | ** 68 | ** OUTPUT REQUESTS 69 | ** 70 | *Restart, write, frequency=0 71 | ** 72 | ** FIELD OUTPUT: F-Output-1 73 | ** 74 | *Output, field, variable=PRESELECT 75 | ** 76 | ** HISTORY OUTPUT: H-Output-1 77 | ** 78 | *Output, history, variable=PRESELECT 79 | ** 80 | ** Output to ASCII-file 81 | ** 82 | *FILE FORMAT, ASCII 83 | ** 84 | *EL FILE 85 | S, E, COORD 86 | ** 87 | *NODE FILE 88 | COORD, U 89 | ** 90 | *End Step 91 | -------------------------------------------------------------------------------- /tests/abaqus/input/quad_CPE4.inp: -------------------------------------------------------------------------------- 1 | *Heading 2 | Test elements of the type CPE4 with quad shape 3 | *Preprint, echo=NO, model=NO, history=NO, contact=NO 4 | ** 5 | ** PARTS 6 | ** 7 | *Part, name=test_part 8 | *End Part 9 | ** 10 | ** 11 | ** ASSEMBLY 12 | ** 13 | *Assembly, name=Assembly 14 | ** 15 | *Instance, name=test_instance, part=test_part 16 | *Node 17 | 1, 0.1, 0.2 18 | 2, 12.9, 0.2 19 | 3, 0.1, 10.5 20 | 4, 12.9, 10.5 21 | *Element, type=CPE4 22 | 1, 1, 2, 4, 3 23 | *Nset, nset=set-test_part, generate 24 | 1, 4, 1 25 | *Elset, elset=set-test_part 26 | 1, 27 | ** Section: test-section 28 | *Solid Section, elset=set-test_part, material=test-material 29 | 0.1, 30 | *End Instance 31 | ** 32 | *Nset, nset=set_load, internal, instance=test_instance 33 | 4, 3 34 | *Nset, nset=set_bc_1, internal, instance=test_instance 35 | 1, 36 | *Nset, nset=set_bc_2, internal, instance=test_instance 37 | 2, 38 | *End Assembly 39 | ** 40 | ** MATERIALS 41 | ** 42 | *Material, name=test-material 43 | *Elastic 44 | 1e05, 0.25 45 | ** 46 | ** BOUNDARY CONDITIONS 47 | ** 48 | ** Name: test-bc-1 Type: Displacement/Rotation 49 | *Boundary 50 | set_bc_1, 1, 1 51 | set_bc_1, 2, 2 52 | ** Name: test-bc-2 Type: Displacement/Rotation 53 | *Boundary 54 | set_bc_2, 2, 2 55 | ** ---------------------------------------------------------------- 56 | ** 57 | ** STEP: test-step 58 | ** 59 | *Step, name=test-step, nlgeom=NO, inc=10 60 | *Static 61 | 1., 1., 1e-05, 1. 62 | ** 63 | ** LOADS 64 | ** 65 | ** Name: test-load Type: Concentrated force 66 | *Cload 67 | set_load, 2, 1e03 68 | ** 69 | ** OUTPUT REQUESTS 70 | ** 71 | *Restart, write, frequency=0 72 | ** 73 | ** FIELD OUTPUT: F-Output-1 74 | ** 75 | *Output, field, variable=PRESELECT 76 | ** 77 | ** HISTORY OUTPUT: H-Output-1 78 | ** 79 | *Output, history, variable=PRESELECT 80 | ** 81 | ** Output to ASCII-file 82 | ** 83 | *FILE FORMAT, ASCII 84 | ** 85 | *EL FILE 86 | S, E, COORD 87 | ** 88 | *NODE FILE 89 | COORD, U 90 | ** 91 | *End Step 92 | -------------------------------------------------------------------------------- /tests/abaqus/input/quad_CPS4.inp: -------------------------------------------------------------------------------- 1 | *Heading 2 | Test elements of the type CPS4 with quad shape 3 | *Preprint, echo=NO, model=NO, history=NO, contact=NO 4 | ** 5 | ** PARTS 6 | ** 7 | *Part, name=test_part 8 | *End Part 9 | ** 10 | ** 11 | ** ASSEMBLY 12 | ** 13 | *Assembly, name=Assembly 14 | ** 15 | *Instance, name=test_instance, part=test_part 16 | *Node 17 | 1, 0.1, 0.2 18 | 2, 12.9, 0.2 19 | 3, 0.1, 10.5 20 | 4, 12.9, 10.5 21 | *Element, type=CPS4 22 | 1, 1, 2, 4, 3 23 | *Nset, nset=set-test_part, generate 24 | 1, 4, 1 25 | *Elset, elset=set-test_part 26 | 1, 27 | ** Section: test-section 28 | *Solid Section, elset=set-test_part, material=test-material 29 | 0.1, 30 | *End Instance 31 | ** 32 | *Nset, nset=set_load, internal, instance=test_instance 33 | 4, 3 34 | *Nset, nset=set_bc_1, internal, instance=test_instance 35 | 1, 36 | *Nset, nset=set_bc_2, internal, instance=test_instance 37 | 2, 38 | *End Assembly 39 | ** 40 | ** MATERIALS 41 | ** 42 | *Material, name=test-material 43 | *Elastic 44 | 1e05, 0.25 45 | ** 46 | ** BOUNDARY CONDITIONS 47 | ** 48 | ** Name: test-bc-1 Type: Displacement/Rotation 49 | *Boundary 50 | set_bc_1, 1, 1 51 | set_bc_1, 2, 2 52 | ** Name: test-bc-2 Type: Displacement/Rotation 53 | *Boundary 54 | set_bc_2, 2, 2 55 | ** ---------------------------------------------------------------- 56 | ** 57 | ** STEP: test-step 58 | ** 59 | *Step, name=test-step, nlgeom=NO, inc=10 60 | *Static 61 | 1., 1., 1e-05, 1. 62 | ** 63 | ** LOADS 64 | ** 65 | ** Name: test-load Type: Concentrated force 66 | *Cload 67 | set_load, 2, 1e03 68 | ** 69 | ** OUTPUT REQUESTS 70 | ** 71 | *Restart, write, frequency=0 72 | ** 73 | ** FIELD OUTPUT: F-Output-1 74 | ** 75 | *Output, field, variable=PRESELECT 76 | ** 77 | ** HISTORY OUTPUT: H-Output-1 78 | ** 79 | *Output, history, variable=PRESELECT 80 | ** 81 | ** Output to ASCII-file 82 | ** 83 | *FILE FORMAT, ASCII 84 | ** 85 | *EL FILE 86 | S, E, COORD 87 | ** 88 | *NODE FILE 89 | COORD, U 90 | ** 91 | *End Step 92 | -------------------------------------------------------------------------------- /tests/abaqus/input/templates/elem_tri.inp: -------------------------------------------------------------------------------- 1 | *Heading 2 | Test elements of the type {ELEM_TYPE} with triangular shape 3 | *Preprint, echo=NO, model=NO, history=NO, contact=NO 4 | ** 5 | ** PARTS 6 | ** 7 | *Part, name=test_part 8 | *End Part 9 | ** 10 | ** 11 | ** ASSEMBLY 12 | ** 13 | *Assembly, name=Assembly 14 | ** 15 | *Instance, name=test_instance, part=test_part 16 | *Node 17 | 1, 0.1, 0.2 18 | 2, 12.9, 0.2 19 | 3, 0.1, 10.5 20 | *Element, type={ELEM_TYPE} 21 | 1, 1, 2, 3 22 | *Nset, nset=set-test_part, generate 23 | 1, 3, 1 24 | *Elset, elset=set-test_part 25 | 1, 26 | ** Section: test-section 27 | *Solid Section, elset=set-test_part, material=test-material 28 | 0.1, 29 | *End Instance 30 | ** 31 | *Nset, nset=set_load, internal, instance=test_instance 32 | 3 33 | *Nset, nset=set_bc_1, internal, instance=test_instance 34 | 1, 35 | *Nset, nset=set_bc_2, internal, instance=test_instance 36 | 2, 37 | *End Assembly 38 | ** 39 | ** MATERIALS 40 | ** 41 | *Material, name=test-material 42 | *Elastic 43 | 1e05, 0.25 44 | ** 45 | ** BOUNDARY CONDITIONS 46 | ** 47 | ** Name: test-bc-1 Type: Displacement/Rotation 48 | *Boundary 49 | set_bc_1, 1, 1 50 | set_bc_1, 2, 2 51 | ** Name: test-bc-2 Type: Displacement/Rotation 52 | *Boundary 53 | set_bc_2, 2, 2 54 | ** ---------------------------------------------------------------- 55 | ** 56 | ** STEP: test-step 57 | ** 58 | *Step, name=test-step, nlgeom=NO, inc=10 59 | *Static 60 | 1., 1., 1e-05, 1. 61 | ** 62 | ** LOADS 63 | ** 64 | ** Name: test-load Type: Concentrated force 65 | *Cload 66 | set_load, 2, 1e03 67 | ** 68 | ** OUTPUT REQUESTS 69 | ** 70 | *Restart, write, frequency=0 71 | ** 72 | ** FIELD OUTPUT: F-Output-1 73 | ** 74 | *Output, field, variable=PRESELECT 75 | ** 76 | ** HISTORY OUTPUT: H-Output-1 77 | ** 78 | *Output, history, variable=PRESELECT 79 | ** 80 | ** Output to ASCII-file 81 | ** 82 | *FILE FORMAT, ASCII 83 | ** 84 | *EL FILE 85 | S, E, COORD 86 | ** 87 | *NODE FILE 88 | COORD, U 89 | ** 90 | *End Step 91 | -------------------------------------------------------------------------------- /tests/abaqus/input/quad_CPE4H.inp: -------------------------------------------------------------------------------- 1 | *Heading 2 | Test elements of the type CPE4H with quad shape 3 | *Preprint, echo=NO, model=NO, history=NO, contact=NO 4 | ** 5 | ** PARTS 6 | ** 7 | *Part, name=test_part 8 | *End Part 9 | ** 10 | ** 11 | ** ASSEMBLY 12 | ** 13 | *Assembly, name=Assembly 14 | ** 15 | *Instance, name=test_instance, part=test_part 16 | *Node 17 | 1, 0.1, 0.2 18 | 2, 12.9, 0.2 19 | 3, 0.1, 10.5 20 | 4, 12.9, 10.5 21 | *Element, type=CPE4H 22 | 1, 1, 2, 4, 3 23 | *Nset, nset=set-test_part, generate 24 | 1, 4, 1 25 | *Elset, elset=set-test_part 26 | 1, 27 | ** Section: test-section 28 | *Solid Section, elset=set-test_part, material=test-material 29 | 0.1, 30 | *End Instance 31 | ** 32 | *Nset, nset=set_load, internal, instance=test_instance 33 | 4, 3 34 | *Nset, nset=set_bc_1, internal, instance=test_instance 35 | 1, 36 | *Nset, nset=set_bc_2, internal, instance=test_instance 37 | 2, 38 | *End Assembly 39 | ** 40 | ** MATERIALS 41 | ** 42 | *Material, name=test-material 43 | *Elastic 44 | 1e05, 0.25 45 | ** 46 | ** BOUNDARY CONDITIONS 47 | ** 48 | ** Name: test-bc-1 Type: Displacement/Rotation 49 | *Boundary 50 | set_bc_1, 1, 1 51 | set_bc_1, 2, 2 52 | ** Name: test-bc-2 Type: Displacement/Rotation 53 | *Boundary 54 | set_bc_2, 2, 2 55 | ** ---------------------------------------------------------------- 56 | ** 57 | ** STEP: test-step 58 | ** 59 | *Step, name=test-step, nlgeom=NO, inc=10 60 | *Static 61 | 1., 1., 1e-05, 1. 62 | ** 63 | ** LOADS 64 | ** 65 | ** Name: test-load Type: Concentrated force 66 | *Cload 67 | set_load, 2, 1e03 68 | ** 69 | ** OUTPUT REQUESTS 70 | ** 71 | *Restart, write, frequency=0 72 | ** 73 | ** FIELD OUTPUT: F-Output-1 74 | ** 75 | *Output, field, variable=PRESELECT 76 | ** 77 | ** HISTORY OUTPUT: H-Output-1 78 | ** 79 | *Output, history, variable=PRESELECT 80 | ** 81 | ** Output to ASCII-file 82 | ** 83 | *FILE FORMAT, ASCII 84 | ** 85 | *EL FILE 86 | S, E, COORD 87 | ** 88 | *NODE FILE 89 | COORD, U 90 | ** 91 | *End Step 92 | -------------------------------------------------------------------------------- /tests/abaqus/input/quad_CPS4I.inp: -------------------------------------------------------------------------------- 1 | *Heading 2 | Test elements of the type CPS4I with quad shape 3 | *Preprint, echo=NO, model=NO, history=NO, contact=NO 4 | ** 5 | ** PARTS 6 | ** 7 | *Part, name=test_part 8 | *End Part 9 | ** 10 | ** 11 | ** ASSEMBLY 12 | ** 13 | *Assembly, name=Assembly 14 | ** 15 | *Instance, name=test_instance, part=test_part 16 | *Node 17 | 1, 0.1, 0.2 18 | 2, 12.9, 0.2 19 | 3, 0.1, 10.5 20 | 4, 12.9, 10.5 21 | *Element, type=CPS4I 22 | 1, 1, 2, 4, 3 23 | *Nset, nset=set-test_part, generate 24 | 1, 4, 1 25 | *Elset, elset=set-test_part 26 | 1, 27 | ** Section: test-section 28 | *Solid Section, elset=set-test_part, material=test-material 29 | 0.1, 30 | *End Instance 31 | ** 32 | *Nset, nset=set_load, internal, instance=test_instance 33 | 4, 3 34 | *Nset, nset=set_bc_1, internal, instance=test_instance 35 | 1, 36 | *Nset, nset=set_bc_2, internal, instance=test_instance 37 | 2, 38 | *End Assembly 39 | ** 40 | ** MATERIALS 41 | ** 42 | *Material, name=test-material 43 | *Elastic 44 | 1e05, 0.25 45 | ** 46 | ** BOUNDARY CONDITIONS 47 | ** 48 | ** Name: test-bc-1 Type: Displacement/Rotation 49 | *Boundary 50 | set_bc_1, 1, 1 51 | set_bc_1, 2, 2 52 | ** Name: test-bc-2 Type: Displacement/Rotation 53 | *Boundary 54 | set_bc_2, 2, 2 55 | ** ---------------------------------------------------------------- 56 | ** 57 | ** STEP: test-step 58 | ** 59 | *Step, name=test-step, nlgeom=NO, inc=10 60 | *Static 61 | 1., 1., 1e-05, 1. 62 | ** 63 | ** LOADS 64 | ** 65 | ** Name: test-load Type: Concentrated force 66 | *Cload 67 | set_load, 2, 1e03 68 | ** 69 | ** OUTPUT REQUESTS 70 | ** 71 | *Restart, write, frequency=0 72 | ** 73 | ** FIELD OUTPUT: F-Output-1 74 | ** 75 | *Output, field, variable=PRESELECT 76 | ** 77 | ** HISTORY OUTPUT: H-Output-1 78 | ** 79 | *Output, history, variable=PRESELECT 80 | ** 81 | ** Output to ASCII-file 82 | ** 83 | *FILE FORMAT, ASCII 84 | ** 85 | *EL FILE 86 | S, E, COORD 87 | ** 88 | *NODE FILE 89 | COORD, U 90 | ** 91 | *End Step 92 | -------------------------------------------------------------------------------- /tests/abaqus/input/quad_CPS4R.inp: -------------------------------------------------------------------------------- 1 | *Heading 2 | Test elements of the type CPS4R with quad shape 3 | *Preprint, echo=NO, model=NO, history=NO, contact=NO 4 | ** 5 | ** PARTS 6 | ** 7 | *Part, name=test_part 8 | *End Part 9 | ** 10 | ** 11 | ** ASSEMBLY 12 | ** 13 | *Assembly, name=Assembly 14 | ** 15 | *Instance, name=test_instance, part=test_part 16 | *Node 17 | 1, 0.1, 0.2 18 | 2, 12.9, 0.2 19 | 3, 0.1, 10.5 20 | 4, 12.9, 10.5 21 | *Element, type=CPS4R 22 | 1, 1, 2, 4, 3 23 | *Nset, nset=set-test_part, generate 24 | 1, 4, 1 25 | *Elset, elset=set-test_part 26 | 1, 27 | ** Section: test-section 28 | *Solid Section, elset=set-test_part, material=test-material 29 | 0.1, 30 | *End Instance 31 | ** 32 | *Nset, nset=set_load, internal, instance=test_instance 33 | 4, 3 34 | *Nset, nset=set_bc_1, internal, instance=test_instance 35 | 1, 36 | *Nset, nset=set_bc_2, internal, instance=test_instance 37 | 2, 38 | *End Assembly 39 | ** 40 | ** MATERIALS 41 | ** 42 | *Material, name=test-material 43 | *Elastic 44 | 1e05, 0.25 45 | ** 46 | ** BOUNDARY CONDITIONS 47 | ** 48 | ** Name: test-bc-1 Type: Displacement/Rotation 49 | *Boundary 50 | set_bc_1, 1, 1 51 | set_bc_1, 2, 2 52 | ** Name: test-bc-2 Type: Displacement/Rotation 53 | *Boundary 54 | set_bc_2, 2, 2 55 | ** ---------------------------------------------------------------- 56 | ** 57 | ** STEP: test-step 58 | ** 59 | *Step, name=test-step, nlgeom=NO, inc=10 60 | *Static 61 | 1., 1., 1e-05, 1. 62 | ** 63 | ** LOADS 64 | ** 65 | ** Name: test-load Type: Concentrated force 66 | *Cload 67 | set_load, 2, 1e03 68 | ** 69 | ** OUTPUT REQUESTS 70 | ** 71 | *Restart, write, frequency=0 72 | ** 73 | ** FIELD OUTPUT: F-Output-1 74 | ** 75 | *Output, field, variable=PRESELECT 76 | ** 77 | ** HISTORY OUTPUT: H-Output-1 78 | ** 79 | *Output, history, variable=PRESELECT 80 | ** 81 | ** Output to ASCII-file 82 | ** 83 | *FILE FORMAT, ASCII 84 | ** 85 | *EL FILE 86 | S, E, COORD 87 | ** 88 | *NODE FILE 89 | COORD, U 90 | ** 91 | *End Step 92 | -------------------------------------------------------------------------------- /tests/abaqus/input/templates/elem_quad.inp: -------------------------------------------------------------------------------- 1 | *Heading 2 | Test elements of the type {ELEM_TYPE} with quad shape 3 | *Preprint, echo=NO, model=NO, history=NO, contact=NO 4 | ** 5 | ** PARTS 6 | ** 7 | *Part, name=test_part 8 | *End Part 9 | ** 10 | ** 11 | ** ASSEMBLY 12 | ** 13 | *Assembly, name=Assembly 14 | ** 15 | *Instance, name=test_instance, part=test_part 16 | *Node 17 | 1, 0.1, 0.2 18 | 2, 12.9, 0.2 19 | 3, 0.1, 10.5 20 | 4, 12.9, 10.5 21 | *Element, type={ELEM_TYPE} 22 | 1, 1, 2, 4, 3 23 | *Nset, nset=set-test_part, generate 24 | 1, 4, 1 25 | *Elset, elset=set-test_part 26 | 1, 27 | ** Section: test-section 28 | *Solid Section, elset=set-test_part, material=test-material 29 | 0.1, 30 | *End Instance 31 | ** 32 | *Nset, nset=set_load, internal, instance=test_instance 33 | 4, 3 34 | *Nset, nset=set_bc_1, internal, instance=test_instance 35 | 1, 36 | *Nset, nset=set_bc_2, internal, instance=test_instance 37 | 2, 38 | *End Assembly 39 | ** 40 | ** MATERIALS 41 | ** 42 | *Material, name=test-material 43 | *Elastic 44 | 1e05, 0.25 45 | ** 46 | ** BOUNDARY CONDITIONS 47 | ** 48 | ** Name: test-bc-1 Type: Displacement/Rotation 49 | *Boundary 50 | set_bc_1, 1, 1 51 | set_bc_1, 2, 2 52 | ** Name: test-bc-2 Type: Displacement/Rotation 53 | *Boundary 54 | set_bc_2, 2, 2 55 | ** ---------------------------------------------------------------- 56 | ** 57 | ** STEP: test-step 58 | ** 59 | *Step, name=test-step, nlgeom=NO, inc=10 60 | *Static 61 | 1., 1., 1e-05, 1. 62 | ** 63 | ** LOADS 64 | ** 65 | ** Name: test-load Type: Concentrated force 66 | *Cload 67 | set_load, 2, 1e03 68 | ** 69 | ** OUTPUT REQUESTS 70 | ** 71 | *Restart, write, frequency=0 72 | ** 73 | ** FIELD OUTPUT: F-Output-1 74 | ** 75 | *Output, field, variable=PRESELECT 76 | ** 77 | ** HISTORY OUTPUT: H-Output-1 78 | ** 79 | *Output, history, variable=PRESELECT 80 | ** 81 | ** Output to ASCII-file 82 | ** 83 | *FILE FORMAT, ASCII 84 | ** 85 | *EL FILE 86 | S, E, COORD 87 | ** 88 | *NODE FILE 89 | COORD, U 90 | ** 91 | *End Step 92 | -------------------------------------------------------------------------------- /tests/abaqus/input/hex_C3D8.inp: -------------------------------------------------------------------------------- 1 | *Heading 2 | Test elements of the type C3D8 with hex shape 3 | *Preprint, echo=NO, model=NO, history=NO, contact=NO 4 | ** 5 | ** PARTS 6 | ** 7 | *Part, name=test_part 8 | *End Part 9 | ** 10 | ** 11 | ** ASSEMBLY 12 | ** 13 | *Assembly, name=Assembly 14 | ** 15 | *Instance, name=test_instance, part=test_part 16 | *Node 17 | 1, 0.0, 0.0, 0.0 18 | 2, 10.0, 0.0, 0.0 19 | 3, 0.0, 20.0, 0.0 20 | 4, 10.0, 20.0, 0.0 21 | 5, 0.0, 0.0, 30.0 22 | 6, 10.0, 0.0, 30.0 23 | 7, 0.0, 20.0, 30.0 24 | 8, 10.0, 20.0, 30.0 25 | *Element, type=C3D8 26 | 1, 1, 2, 4, 3, 5, 6, 8, 7 27 | *Nset, nset=set-test_part, generate 28 | 1, 8, 1 29 | *Elset, elset=set-test_part 30 | 1, 31 | ** Section: 32 | *Solid Section, elset=set-test_part, material=test-material 33 | 1.0, 34 | *End Instance 35 | ** 36 | *Nset, nset=set_load, internal, instance=test_instance 37 | 5, 6, 7, 8 38 | *Nset, nset=set_bc_1, internal, instance=test_instance 39 | 1 40 | *Nset, nset=set_bc_2, internal, instance=test_instance 41 | 4 42 | *Nset, nset=set_bc_3, internal, instance=test_instance 43 | 2, 3 44 | *End Assembly 45 | ** 46 | ** MATERIALS 47 | ** 48 | *Material, name=test-material 49 | *Elastic 50 | 1e05, 0.25 51 | ** 52 | ** BOUNDARY CONDITIONS 53 | ** 54 | *Boundary 55 | set_bc_1, 1, 3 56 | set_bc_2, 1 57 | set_bc_2, 3 58 | set_bc_3, 3, 3 59 | ** ---------------------------------------------------------------- 60 | ** 61 | ** STEP: 62 | ** 63 | *Step, name=test-step, nlgeom=NO, inc=10 64 | *Static 65 | 1., 1., 1e-05, 1. 66 | ** 67 | ** LOADS 68 | ** 69 | *Cload 70 | set_load, 2, 1e03 71 | ** 72 | ** OUTPUT REQUESTS 73 | ** 74 | *Restart, write, frequency=0 75 | ** 76 | ** FIELD OUTPUT: F-Output-1 77 | ** 78 | *Output, field, variable=PRESELECT 79 | ** 80 | ** HISTORY OUTPUT: H-Output-1 81 | ** 82 | *Output, history, variable=PRESELECT 83 | ** 84 | ** Output to ASCII-file 85 | ** 86 | *FILE FORMAT, ASCII 87 | ** 88 | *EL FILE 89 | S, E, COORD 90 | ** 91 | *NODE FILE 92 | COORD, U 93 | ** 94 | *End Step 95 | -------------------------------------------------------------------------------- /tests/abaqus/input/templates/elem_hex.inp: -------------------------------------------------------------------------------- 1 | *Heading 2 | Test elements of the type {ELEM_TYPE} with hex shape 3 | *Preprint, echo=NO, model=NO, history=NO, contact=NO 4 | ** 5 | ** PARTS 6 | ** 7 | *Part, name=test_part 8 | *End Part 9 | ** 10 | ** 11 | ** ASSEMBLY 12 | ** 13 | *Assembly, name=Assembly 14 | ** 15 | *Instance, name=test_instance, part=test_part 16 | *Node 17 | 1, 0.0, 0.0, 0.0 18 | 2, 10.0, 0.0, 0.0 19 | 3, 0.0, 20.0, 0.0 20 | 4, 10.0, 20.0, 0.0 21 | 5, 0.0, 0.0, 30.0 22 | 6, 10.0, 0.0, 30.0 23 | 7, 0.0, 20.0, 30.0 24 | 8, 10.0, 20.0, 30.0 25 | *Element, type={ELEM_TYPE} 26 | 1, 1, 2, 4, 3, 5, 6, 8, 7 27 | *Nset, nset=set-test_part, generate 28 | 1, 8, 1 29 | *Elset, elset=set-test_part 30 | 1, 31 | ** Section: 32 | *Solid Section, elset=set-test_part, material=test-material 33 | 1.0, 34 | *End Instance 35 | ** 36 | *Nset, nset=set_load, internal, instance=test_instance 37 | 5, 6, 7, 8 38 | *Nset, nset=set_bc_1, internal, instance=test_instance 39 | 1 40 | *Nset, nset=set_bc_2, internal, instance=test_instance 41 | 4 42 | *Nset, nset=set_bc_3, internal, instance=test_instance 43 | 2, 3 44 | *End Assembly 45 | ** 46 | ** MATERIALS 47 | ** 48 | *Material, name=test-material 49 | *Elastic 50 | 1e05, 0.25 51 | ** 52 | ** BOUNDARY CONDITIONS 53 | ** 54 | *Boundary 55 | set_bc_1, 1, 3 56 | set_bc_2, 1 57 | set_bc_2, 3 58 | set_bc_3, 3, 3 59 | ** ---------------------------------------------------------------- 60 | ** 61 | ** STEP: 62 | ** 63 | *Step, name=test-step, nlgeom=NO, inc=10 64 | *Static 65 | 1., 1., 1e-05, 1. 66 | ** 67 | ** LOADS 68 | ** 69 | *Cload 70 | set_load, 3, 1e03 71 | ** 72 | ** OUTPUT REQUESTS 73 | ** 74 | *Restart, write, frequency=0 75 | ** 76 | ** FIELD OUTPUT: F-Output-1 77 | ** 78 | *Output, field, variable=PRESELECT 79 | ** 80 | ** HISTORY OUTPUT: H-Output-1 81 | ** 82 | *Output, history, variable=PRESELECT 83 | ** 84 | ** Output to ASCII-file 85 | ** 86 | *FILE FORMAT, ASCII 87 | ** 88 | *EL FILE 89 | S, E, COORD 90 | ** 91 | *NODE FILE 92 | COORD, U 93 | ** 94 | *End Step 95 | -------------------------------------------------------------------------------- /tests/abaqus/input/discontinuous_numbering_2D.inp: -------------------------------------------------------------------------------- 1 | *Heading 2 | An example with a dicontinuous numbering of the nodes 3 | *Preprint, echo=NO, model=NO, history=NO, contact=NO 4 | ** 5 | ** PARTS 6 | ** 7 | *Part, name=test_part 8 | *End Part 9 | ** 10 | ** 11 | ** ASSEMBLY 12 | ** 13 | *Assembly, name=Assembly 14 | ** 15 | *Instance, name=test_instance, part=test_part 16 | *Node 17 | 1, 0.0, 0.0 18 | 2, 10.0, 0.0 19 | 3, 0.0, 10.0 20 | 4, 10.0, 10.0 21 | 7, 20.0, 0.0 22 | 8, 20.0, 10.0 23 | *Element, type=CPS4 24 | 1, 1, 2, 4, 3 25 | 2, 2, 7, 8, 4 26 | *Nset, nset=set-test_part 27 | 1, 2, 3, 4, 7, 8 28 | *Elset, elset=set-test_part 29 | 1, 2 30 | ** Section: test-section 31 | *Solid Section, elset=set-test_part, material=test-material 32 | 0.1, 33 | *End Instance 34 | ** 35 | *Nset, nset=set_load, internal, instance=test_instance 36 | 4, 3, 8 37 | *Nset, nset=set_bc_1, internal, instance=test_instance 38 | 1, 39 | *Nset, nset=set_bc_2, internal, instance=test_instance 40 | 2, 7 41 | *End Assembly 42 | ** 43 | ** MATERIALS 44 | ** 45 | *Material, name=test-material 46 | *Elastic 47 | 1e05, 0.25 48 | ** 49 | ** BOUNDARY CONDITIONS 50 | ** 51 | ** Name: test-bc-1 Type: Displacement/Rotation 52 | *Boundary 53 | set_bc_1, 1, 1 54 | set_bc_1, 2, 2 55 | ** Name: test-bc-2 Type: Displacement/Rotation 56 | *Boundary 57 | set_bc_2, 2, 2 58 | ** ---------------------------------------------------------------- 59 | ** 60 | ** STEP: test-step 61 | ** 62 | *Step, name=test-step, nlgeom=NO, inc=10 63 | *Static 64 | 1., 1., 1e-05, 1. 65 | ** 66 | ** LOADS 67 | ** 68 | ** Name: test-load Type: Concentrated force 69 | *Cload 70 | set_load, 2, 1e03 71 | ** 72 | ** OUTPUT REQUESTS 73 | ** 74 | *Restart, write, frequency=0 75 | ** 76 | ** FIELD OUTPUT: F-Output-1 77 | ** 78 | *Output, field, variable=PRESELECT 79 | ** 80 | ** HISTORY OUTPUT: H-Output-1 81 | ** 82 | *Output, history, variable=PRESELECT 83 | ** 84 | ** Output to ASCII-file 85 | ** 86 | *FILE FORMAT, ASCII 87 | ** 88 | *EL FILE 89 | S, E, COORD 90 | ** 91 | *NODE FILE 92 | COORD, U 93 | ** 94 | *End Step 95 | -------------------------------------------------------------------------------- /tests/test_data/element_results.py: -------------------------------------------------------------------------------- 1 | """Test data for element result validation""" 2 | 3 | import numpy as np 4 | 5 | ELEMENT_QUAD_TYPES = [ 6 | { 7 | "name": "CPE4", 8 | "variable": "S1", 9 | "expected": np.array([2.273737e-13, -3.105982e-13, 8.322454e-14, 2.273737e-13]), 10 | }, 11 | { 12 | "name": "CPE4H", 13 | "variable": "S1", 14 | "expected": np.array( 15 | [-1.705302e-13, -9.845562e-14, 9.845596e-14, -1.705300e-13] 16 | ), 17 | }, 18 | { 19 | "name": "CPS4", 20 | "variable": "S1", 21 | "expected": np.array( 22 | [1.213024e-13, -3.542511e-13, -1.573397e-13, 2.197581e-13] 23 | ), 24 | }, 25 | { 26 | "name": "CPS4I", 27 | "variable": "S1", 28 | "expected": np.array([2.040588e-15, -3.029826e-13, 1.892958e-13, 3.958633e-13]), 29 | }, 30 | { 31 | "name": "CPS4R", 32 | "variable": "S1", 33 | "expected": np.array([1.705303e-13, 1.705303e-13, 1.705303e-13, 1.705303e-13]), 34 | }, 35 | ] 36 | 37 | # Elements with triangular shapes 38 | ELEMENT_TRI_TYPES = [ 39 | { 40 | "name": "CPE3", 41 | "variable": "S1", 42 | "expected": np.array([1.136868e-13, 1.136868e-13, 1.136868e-13]), 43 | }, 44 | { 45 | "name": "CPE3H", 46 | "variable": "S1", 47 | "expected": np.array([-1.136868e-13, -1.136868e-13, -1.136868e-13]), 48 | }, 49 | { 50 | "name": "CPS3", 51 | "variable": "S1", 52 | "expected": np.array([5.684342e-14, 5.684342e-14, 5.684342e-14]), 53 | }, 54 | ] 55 | 56 | # 3D Elements with hexagonal shapes 57 | ELEMENT_HEX_TYPES = [ 58 | { 59 | "name": "C3D8", 60 | "variable": "S1", 61 | "expected": np.array( 62 | [ 63 | -14.264411, 64 | 19.535111, 65 | -8.00401, 66 | 24.748814, 67 | 2.043412, 68 | -12.121549, 69 | 8.303813, 70 | -6.907847, 71 | ] 72 | ), 73 | }, 74 | ] 75 | -------------------------------------------------------------------------------- /examples/Displacement_visualization/model.inp: -------------------------------------------------------------------------------- 1 | *Heading 2 | ** Job name: OptislangTest1 Model name: Model-1 3 | ** Generated by: Abaqus/CAE 2019 4 | *Preprint, echo=NO, model=NO, history=NO, contact=NO 5 | ** 6 | ** PARTS 7 | ** 8 | *Part, name=Part-1 9 | *Node 10 | 1, 0., 0. 11 | 2, 2.5, 0. 12 | 3, 5., 0. 13 | 4, 0., 2.5 14 | 5, 2.5, 2.5 15 | 6, 5., 2.5 16 | 7, 0., 5. 17 | 8, 2.5, 5. 18 | 9, 5., 5. 19 | *Element, type=CAX4 20 | 1, 1, 2, 5, 4 21 | 2, 2, 3, 6, 5 22 | 3, 4, 5, 8, 7 23 | 4, 5, 6, 9, 8 24 | *Nset, nset=Set-1, generate 25 | 1, 9, 1 26 | *Elset, elset=Set-1, generate 27 | 1, 4, 1 28 | ** Section: Section-1 29 | *Solid Section, elset=Set-1, material=Material-1 30 | , 31 | *End Part 32 | ** 33 | ** 34 | ** ASSEMBLY 35 | ** 36 | *Assembly, name=Assembly 37 | ** 38 | *Instance, name=Part-1-1, part=Part-1 39 | *End Instance 40 | ** 41 | *Nset, nset=Set-1, instance=Part-1-1, generate 42 | 1, 7, 3 43 | *Elset, elset=Set-1, instance=Part-1-1 44 | 1, 3 45 | *Nset, nset=Set-2, instance=Part-1-1, generate 46 | 1, 3, 1 47 | *Elset, elset=Set-2, instance=Part-1-1 48 | 1, 2 49 | *Elset, elset=_Surf-1_S3, internal, instance=Part-1-1 50 | 3, 4 51 | *Surface, type=ELEMENT, name=Surf-1 52 | _Surf-1_S3, S3 53 | *End Assembly 54 | ** 55 | ** MATERIALS 56 | ** 57 | *Material, name=Material-1 58 | *Elastic 59 | 2e+06, 0.3 60 | ** ---------------------------------------------------------------- 61 | ** 62 | ** STEP: Step-1 63 | ** 64 | *Step, name=Step-1, nlgeom=NO 65 | *Static 66 | 1., 1., 1e-05, 1. 67 | ** 68 | ** BOUNDARY CONDITIONS 69 | ** 70 | ** Name: BC-X Type: Displacement/Rotation 71 | *Boundary 72 | Set-1, 1, 1 73 | ** Name: BC-Y Type: Displacement/Rotation 74 | *Boundary 75 | Set-2, 2, 2 76 | ** 77 | ** LOADS 78 | ** 79 | ** Name: Load-1 Type: Pressure 80 | *Dsload 81 | Surf-1, P, -100. 82 | ** 83 | ** OUTPUT REQUESTS 84 | ** 85 | *Restart, write, frequency=0 86 | ** 87 | ** FIELD OUTPUT: F-Output-1 88 | ** 89 | *Output, field, variable=PRESELECT 90 | ** 91 | ** HISTORY OUTPUT: H-Output-1 92 | ** 93 | *Output, history, variable=PRESELECT 94 | *FILE FORMAT, ASCII 95 | *NODE FILE 96 | U 97 | *End Step 98 | -------------------------------------------------------------------------------- /tests/test_elements.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from numpy.testing import assert_allclose 3 | from test_data.element_results import ( 4 | ELEMENT_HEX_TYPES, 5 | ELEMENT_QUAD_TYPES, 6 | ELEMENT_TRI_TYPES, 7 | ) 8 | 9 | from pybaqus.reader import open_fil, read_records 10 | 11 | 12 | @pytest.mark.parametrize("test_case", ELEMENT_QUAD_TYPES, ids=lambda x: x["name"]) 13 | def test_element_quad(test_case): 14 | """Test element stress results for different element types. 15 | 16 | Parameters 17 | ---------- 18 | test_case: 19 | Dictionary containing test parameters and expected results 20 | """ 21 | model = open_fil(f"tests/abaqus/fil/quad_{test_case['name']}.fil") 22 | stress = model.get_nodal_result(var=test_case["variable"], step=1, inc=1) 23 | assert_allclose( 24 | stress, 25 | test_case["expected"], 26 | err_msg=f"Failed for element type: {test_case['name']}", 27 | rtol=1e-6, 28 | ) 29 | 30 | 31 | @pytest.mark.parametrize("test_case", ELEMENT_TRI_TYPES, ids=lambda x: x["name"]) 32 | def test_element_tri(test_case): 33 | """Test element stress results for different element types. 34 | 35 | Parameters 36 | ---------- 37 | test_case: 38 | Dictionary containing test parameters and expected results 39 | """ 40 | model = open_fil(f"tests/abaqus/fil/tri_{test_case['name']}.fil") 41 | stress = model.get_nodal_result(var=test_case["variable"], step=1, inc=1) 42 | assert_allclose( 43 | stress, 44 | test_case["expected"], 45 | err_msg=f"Failed for element type: {test_case['name']}", 46 | rtol=1e-6, 47 | ) 48 | 49 | 50 | @pytest.mark.parametrize("test_case", ELEMENT_HEX_TYPES, ids=lambda x: x["name"]) 51 | def test_element_hex(test_case): 52 | """Test element stress results for different element types. 53 | 54 | Parameters 55 | ---------- 56 | test_case: 57 | Dictionary containing test parameters and expected results 58 | """ 59 | model = open_fil(f"tests/abaqus/fil/hex_{test_case['name']}.fil") 60 | stress = model.get_nodal_result(var=test_case["variable"], step=1, inc=1) 61 | assert_allclose( 62 | stress, 63 | test_case["expected"], 64 | err_msg=f"Failed for element type: {test_case['name']}", 65 | rtol=1e-6, 66 | ) 67 | -------------------------------------------------------------------------------- /tests/abaqus/fil/tri_CPE3.fil: -------------------------------------------------------------------------------- 1 | *I 19I 41921A6.23-1 A06-Nov-2A024 A17:15:35I 11I 13D 1.155000000000000D+01* 2 | I 17I 41900I 11ACPE3 I 11I 12I 13*I 15I 41901I 11D 1.000000000000000D-01D 2.0 3 | 00000000000000D-01*I 15I 41901I 12D 1.290000000000000D+01D 2.000000000000000D-01 4 | *I 15I 41901I 13D 1.000000000000000D-01D 1.050000000000000D+01*I 14I 41933A 5 | 1I 11*I 16I 41931A 1I 11I 12I 13*I 14I 41931A 2I 11*I 14I 41931A 6 | 3I 12*I 14I 41931A 4I 13*I 18I 41940I 11AASSEMBLYA_TEST_INASTANCE_SAE 7 | T-TEST_APART *I 16I 41940I 12AASSEMBLYA_SET_BC_A1 *I 16I 41940I 13AASSE 8 | MBLYA_SET_BC_A2 *I 16I 41940I 14AASSEMBLYA_SET_LOAAD *I 15I 41940I 1 9 | 5ATEST-MATAERIAL *I 15I 41940I 16A NODES_ZAERO_AREA*I 15I 41940I 17AANTIALIAAS 10 | ING *I 15I 41940I 18Atest-steAp *I 236I 41902I 11I 12I 10I 10I 10I 10I 11 | 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 12 | 10I 10I 10I 10I 10I 10I 10I 10*I 212I 41922ATest eleAments ofA the typAe CPE3 wA 13 | ith triaAngular sAhape A A A *I 12I 42001 14 | 15 | *I 223I 42000D 1.000000000000000D+00D 1.000000000000000D+00D 0.000000000000000D+ 16 | 00D 0.000000000000000D+00I 11I 11I 11I 10D 0.000000000000000D+00D 0.000000000000 17 | 000D+00D 1.000000000000000D+00A A A A A A 18 | A A A A *I 15I 41911I 10A ACPE3 *I 211 19 | I 11I 11I 11I 10I 10A I 13I 11I 10I 10*I 16I 211D 1.136868377216160D-13D 20 | 1.562500000000000D+03D 3.906249999999999D+02D 0.000000000000000D+00*I 16I 221D-4 21 | .882812499999998D-03D 1.464843750000000D-02D 0.000000000000000D+00D 0.0000000000 22 | 00000D+00*I 14I 18D 4.366666666666666D+00D 3.633333333333333D+00*I 14I 41911I 11 23 | A *I 15I 3107I 11D 1.000000000000000D-01D 2.000000000000000D-01*I 15I 310 24 | 7I 12D 1.290000000000000D+01D 2.000000000000000D-01*I 15I 3107I 13D 1.0000000000 25 | 00000D-01D 1.050000000000000D+01*I 15I 3101I 11D 0.000000000000000D+00D 1.000000 26 | 000000000D-33*I 15I 3101I 12D-6.249999999999997D-02D 0.000000000000000D+00*I 15I 27 | 3101I 13D 8.046874999999997D-34D 1.508789062499999D-01*I 12I 42001 28 | 29 | -------------------------------------------------------------------------------- /tests/abaqus/fil/tri_CPS3.fil: -------------------------------------------------------------------------------- 1 | *I 19I 41921A6.23-1 A06-Nov-2A024 A17:12:00I 11I 13D 1.155000000000000D+01* 2 | I 17I 41900I 11ACPS3 I 11I 12I 13*I 15I 41901I 11D 1.000000000000000D-01D 2.0 3 | 00000000000000D-01*I 15I 41901I 12D 1.290000000000000D+01D 2.000000000000000D-01 4 | *I 15I 41901I 13D 1.000000000000000D-01D 1.050000000000000D+01*I 14I 41933A 5 | 1I 11*I 16I 41931A 1I 11I 12I 13*I 14I 41931A 2I 11*I 14I 41931A 6 | 3I 12*I 14I 41931A 4I 13*I 18I 41940I 11AASSEMBLYA_TEST_INASTANCE_SAE 7 | T-TEST_APART *I 16I 41940I 12AASSEMBLYA_SET_BC_A1 *I 16I 41940I 13AASSE 8 | MBLYA_SET_BC_A2 *I 16I 41940I 14AASSEMBLYA_SET_LOAAD *I 15I 41940I 1 9 | 5ATEST-MATAERIAL *I 15I 41940I 16A NODES_ZAERO_AREA*I 15I 41940I 17AANTIALIAAS 10 | ING *I 15I 41940I 18Atest-steAp *I 236I 41902I 11I 12I 10I 10I 10I 10I 11 | 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 12 | 10I 10I 10I 10I 10I 10I 10I 10*I 212I 41922ATest eleAments ofA the typAe CPS3 wA 13 | ith triaAngular sAhape A A A *I 12I 42001 14 | 15 | *I 223I 42000D 1.000000000000000D+00D 1.000000000000000D+00D 0.000000000000000D+ 16 | 00D 0.000000000000000D+00I 11I 11I 11I 10D 0.000000000000000D+00D 0.000000000000 17 | 000D+00D 1.000000000000000D+00A A A A A A 18 | A A A A *I 15I 41911I 10A ACPS3 *I 211 19 | I 11I 11I 11I 10I 10A I 12I 11I 10I 10*I 15I 211D 5.684341886080801D-14D 20 | 1.562500000000000D+03D 0.000000000000000D+00*I 15I 221D-3.906249999999998D-03D 1 21 | .562499999999999D-02D 0.000000000000000D+00*I 14I 18D 4.366666666666666D+00D 3.6 22 | 33333333333333D+00*I 14I 41911I 11A *I 15I 3107I 11D 1.000000000000000D-0 23 | 1D 2.000000000000000D-01*I 15I 3107I 12D 1.290000000000000D+01D 2.00000000000000 24 | 0D-01*I 15I 3107I 13D 1.000000000000000D-01D 1.050000000000000D+01*I 15I 3101I 1 25 | 1D 0.000000000000000D+00D 1.000000000000000D-33*I 15I 3101I 12D-4.99999999999999 26 | 8D-02D 0.000000000000000D+00*I 15I 3101I 13D 8.046875000000000D-34D 1.6093749999 27 | 99999D-01*I 12I 42001 28 | 29 | -------------------------------------------------------------------------------- /tests/abaqus/fil/tri_CPE3H.fil: -------------------------------------------------------------------------------- 1 | *I 19I 41921A6.23-1 A06-Nov-2A024 A17:15:31I 11I 13D 1.155000000000000D+01* 2 | I 17I 41900I 11ACPE3H I 11I 12I 13*I 15I 41901I 11D 1.000000000000000D-01D 2.0 3 | 00000000000000D-01*I 15I 41901I 12D 1.290000000000000D+01D 2.000000000000000D-01 4 | *I 15I 41901I 13D 1.000000000000000D-01D 1.050000000000000D+01*I 14I 41933A 5 | 1I 11*I 16I 41931A 1I 11I 12I 13*I 14I 41931A 2I 11*I 14I 41931A 6 | 3I 12*I 14I 41931A 4I 13*I 18I 41940I 11AASSEMBLYA_TEST_INASTANCE_SAE 7 | T-TEST_APART *I 16I 41940I 12AASSEMBLYA_SET_BC_A1 *I 16I 41940I 13AASSE 8 | MBLYA_SET_BC_A2 *I 16I 41940I 14AASSEMBLYA_SET_LOAAD *I 15I 41940I 1 9 | 5ATEST-MATAERIAL *I 15I 41940I 16A NODES_ZAERO_AREA*I 15I 41940I 17AANTIALIAAS 10 | ING *I 15I 41940I 18Atest-steAp *I 236I 41902I 11I 12I 10I 10I 10I 10I 11 | 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 12 | 10I 10I 10I 10I 10I 10I 10I 10*I 212I 41922ATest eleAments ofA the typAe CPE3H A 13 | with triAangular Ashape A A A *I 12I 42001 14 | 15 | *I 223I 42000D 1.000000000000000D+00D 1.000000000000000D+00D 0.000000000000000D+ 16 | 00D 0.000000000000000D+00I 11I 11I 11I 10D 0.000000000000000D+00D 0.000000000000 17 | 000D+00D 1.000000000000000D+00A A A A A A 18 | A A A A *I 15I 41911I 10A ACPE3H *I 211 19 | I 11I 11I 11I 10I 10A I 13I 11I 10I 10*I 16I 211D-1.136868377216160D-13D 20 | 1.562500000000000D+03D 3.906250000000000D+02D 0.000000000000000D+00*I 16I 221D-4 21 | .882812500000001D-03D 1.464843750000000D-02D 0.000000000000000D+00D 0.0000000000 22 | 00000D+00*I 14I 18D 4.366666666666666D+00D 3.633333333333333D+00*I 14I 41911I 11 23 | A *I 15I 3107I 11D 1.000000000000000D-01D 2.000000000000000D-01*I 15I 310 24 | 7I 12D 1.290000000000000D+01D 2.000000000000000D-01*I 15I 3107I 13D 1.0000000000 25 | 00000D-01D 1.050000000000000D+01*I 15I 3101I 11D 0.000000000000000D+00D 1.000000 26 | 000000000D-33*I 15I 3101I 12D-6.250000000000001D-02D 0.000000000000000D+00*I 15I 27 | 3101I 13D 8.046874999999999D-34D 1.508789062500000D-01*I 12I 42001 28 | 29 | -------------------------------------------------------------------------------- /tests/abaqus/fil/quad_CPS4R.fil: -------------------------------------------------------------------------------- 1 | *I 19I 41921A6.23-1 A07-Nov-2A024 A16:49:36I 11I 14D 1.155000000000000D+01* 2 | I 18I 41900I 11ACPS4R I 11I 12I 14I 13*I 15I 41901I 11D 1.000000000000000D-01D 3 | 2.000000000000000D-01*I 15I 41901I 12D 1.290000000000000D+01D 2.000000000000000 4 | D-01*I 15I 41901I 13D 1.000000000000000D-01D 1.050000000000000D+01*I 15I 41901I 5 | 14D 1.290000000000000D+01D 1.050000000000000D+01*I 14I 41933A 1I 11*I 17I 6 | 41931A 1I 11I 12I 13I 14*I 14I 41931A 2I 11*I 14I 41931A 3I 12 7 | *I 15I 41931A 4I 13I 14*I 18I 41940I 11AASSEMBLYA_TEST_INASTANCE_SAET-TEST 8 | _APART *I 16I 41940I 12AASSEMBLYA_SET_BC_A1 *I 16I 41940I 13AASSEMBLYA_ 9 | SET_BC_A2 *I 16I 41940I 14AASSEMBLYA_SET_LOAAD *I 15I 41940I 15ATEST 10 | -MATAERIAL *I 15I 41940I 16A NODES_ZAERO_AREA*I 15I 41940I 17AANTIALIAASING 11 | *I 15I 41940I 18Atest-steAp *I 236I 41902I 11I 12I 10I 10I 10I 10I 10I 10 12 | I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10 13 | I 10I 10I 10I 10I 10I 10*I 212I 41922ATest eleAments ofA the typAe CPS4R Awith q 14 | uaAd shape A A A A *I 12I 42001 15 | 16 | *I 223I 42000D 1.000000000000000D+00D 1.000000000000000D+00D 0.000000000000000D+ 17 | 00D 0.000000000000000D+00I 11I 11I 11I 10D 0.000000000000000D+00D 0.000000000000 18 | 000D+00D 1.000000000000000D+00A A A A A A 19 | A A A A *I 15I 41911I 10A ACPS4R *I 211 20 | I 11I 11I 11I 10I 10A I 12I 11I 10I 10*I 15I 211D 1.705302565824240D-13D 21 | 1.562500000000000D+03D-6.938893903907228D-14*I 15I 221D-3.906249999999997D-03D 1 22 | .562499999999999D-02D-1.734723475976807D-18*I 14I 18D 6.500000000000000D+00D 5.3 23 | 50000000000000D+00*I 14I 41911I 11A *I 15I 3107I 11D 1.000000000000000D-0 24 | 1D 2.000000000000000D-01*I 15I 3107I 12D 1.290000000000000D+01D 2.00000000000000 25 | 0D-01*I 15I 3107I 13D 1.000000000000000D-01D 1.050000000000000D+01*I 15I 3107I 1 26 | 4D 1.290000000000000D+01D 1.050000000000000D+01*I 15I 3101I 11D 0.00000000000000 27 | 0D+00D 1.000000000000000D-33*I 15I 3101I 12D-5.000000000000339D-02D 9.9999999999 28 | 99999D-34*I 15I 3101I 13D-1.276756478318930D-15D 1.609375000000026D-01*I 15I 310 29 | 1I 14D-4.999999999999781D-02D 1.609374999999972D-01*I 12I 42001 30 | 31 | -------------------------------------------------------------------------------- /.github/workflows/python-publish.yml: -------------------------------------------------------------------------------- 1 | # This workflow will upload a Python Package to PyPI when a release is created 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries 3 | 4 | # This workflow uses actions that are not certified by GitHub. 5 | # They are provided by a third-party and are governed by 6 | # separate terms of service, privacy policy, and support 7 | # documentation. 8 | 9 | name: Upload Python Package 10 | 11 | on: 12 | release: 13 | types: [published] 14 | 15 | permissions: 16 | contents: read 17 | 18 | jobs: 19 | release-build: 20 | runs-on: ubuntu-latest 21 | 22 | steps: 23 | - uses: actions/checkout@v4 24 | 25 | - name: Install uv 26 | uses: astral-sh/setup-uv@v5 27 | with: 28 | # Install a specific version of uv. 29 | version: "0.6.9" 30 | 31 | - name: "Set up Python" 32 | uses: actions/setup-python@v5 33 | with: 34 | python-version-file: "pyproject.toml" 35 | 36 | - name: Build release distributions 37 | run: uv build 38 | 39 | - name: Upload distributions 40 | uses: actions/upload-artifact@v4 41 | with: 42 | name: release-dists 43 | path: dist/ 44 | 45 | pypi-publish: 46 | runs-on: ubuntu-latest 47 | needs: 48 | - release-build 49 | permissions: 50 | # IMPORTANT: this permission is mandatory for trusted publishing 51 | id-token: write 52 | 53 | # Dedicated environments with protections for publishing are strongly recommended. 54 | # For more information, see: https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment#deployment-protection-rules 55 | environment: 56 | name: pypi 57 | # OPTIONAL: uncomment and update to include your PyPI project URL in the deployment status: 58 | url: https://pypi.org/p/pybaqus 59 | # 60 | # ALTERNATIVE: if your GitHub Release name is the PyPI project version string 61 | # ALTERNATIVE: exactly, uncomment the following line instead: 62 | # url: https://pypi.org/project/YOURPROJECT/${{ github.event.release.name }} 63 | 64 | steps: 65 | - name: Retrieve release distributions 66 | uses: actions/download-artifact@v4 67 | with: 68 | name: release-dists 69 | path: dist/ 70 | 71 | - name: Publish release distributions to PyPI 72 | uses: pypa/gh-action-pypi-publish@release/v1 73 | with: 74 | packages-dir: dist/ 75 | -------------------------------------------------------------------------------- /tests/abaqus/Makefile: -------------------------------------------------------------------------------- 1 | # This makefile is used to generate and run the input files for different tests. 2 | # 3 | # To run all the tests: 4 | # > make all 5 | # 6 | 7 | SHELL:=/bin/bash 8 | 9 | INP_FILES := $(wildcard input/*.inp) 10 | FIL_FILES := $(subst input,fil,$(subst .inp,.fil,$(INP_FILES))) 11 | 12 | # Define the element types used to generate corresponding *.inp files 13 | ELEM_TYPES_QUAD_4 := CPE4 CPE4H CPS4 CPS4I CPS4R 14 | ELEM_TYPES_TRI_3 := CPE3 CPE3H CPS3 15 | ELEM_TYPES_QUAD_8 := CPS8 16 | ELEM_TYPES_HEX_8 := C3D8 17 | 18 | # Generate paths for input files 19 | INP_TARGETS_QUAD := $(addprefix input/quad_,$(addsuffix .inp,$(ELEM_TYPES_QUAD_4))) 20 | INP_TARGETS_TRI := $(addprefix input/tri_,$(addsuffix .inp,$(ELEM_TYPES_TRI_3))) 21 | INP_TARGETS_HEX := $(addprefix input/hex_,$(addsuffix .inp,$(ELEM_TYPES_HEX_8))) 22 | 23 | INP_TARGETS := $(INP_TARGETS_TRI) $(INP_TARGETS_QUAD) $(INP_TARGETS_HEX) 24 | 25 | .PHONY: all clear 26 | 27 | all: $(INP_TARGETS) $(FIL_FILES) 28 | 29 | # This rule runs each input file in the directory 30 | fil/%.fil: input/%.inp 31 | @echo "> Starting Abaqus job $*..." 32 | @rm -f fil/$*.fil 2>/dev/null 33 | @abq2023 job=$* input=$< || { \ 34 | echo " Abaqus failed to start"; \ 35 | exit 1; \ 36 | } 37 | @until [ -f $*.sta ]; do \ 38 | if ! pgrep -f "abq2023.*job=$*" >/dev/null; then \ 39 | echo " Process terminated unexpectedly before .sta file was created"; \ 40 | [ -f $*.msg ] && { echo "Last few lines of message file:"; tail -n 20 $*.msg; }; \ 41 | exit 1; \ 42 | fi; \ 43 | sleep 2; \ 44 | done 45 | @# Check that the analysis has finished correctly 46 | @until grep -q "THE ANALYSIS HAS COMPLETED SUCCESSFULLY" $*.sta 2>/dev/null; do \ 47 | if ! pgrep -f "abq2023.*job=$*" >/dev/null; then \ 48 | echo " Process terminated unexpectedly during analysis"; \ 49 | echo " Last few lines of status file:"; \ 50 | tail -n 20 $*.sta 2>/dev/null || true; \ 51 | [ -f $*.msg ] && { echo " Last few lines of message file:"; tail -n 20 $*.msg; }; \ 52 | exit 1; \ 53 | fi; \ 54 | sleep 2; \ 55 | done 56 | @# Check that the lock file is gone 57 | @until [ ! -f $*.lck ]; do \ 58 | sleep 1; \ 59 | done 60 | @echo " Analysis for $* completed successfully" 61 | @rm -f $*.dat $*.odb $*.com $*.msg $*.sta $*.log $*.prt 62 | @mv $*.fil fil/$*.fil 63 | 64 | # Generate individual input files per element type with quad shape 65 | input/quad_%.inp: input/templates/elem_quad.inp 66 | @mkdir -p input 67 | @echo "Generating input file for element type $*..." 68 | @sed -e 's/{ELEM_TYPE}/$*/g' $< > $@ 69 | 70 | # Generate individual input files per element type with triangular shape 71 | input/tri_%.inp: input/templates/elem_tri.inp 72 | @mkdir -p input 73 | @echo "Generating input file for element type $*..." 74 | @sed -e 's/{ELEM_TYPE}/$*/g' $< > $@ 75 | 76 | # Generate individual input files per element type with hexagonal shape 77 | input/hex_%.inp: input/templates/elem_hex.inp 78 | @mkdir -p input 79 | @echo "Generating input file for element type $*..." 80 | @sed -e 's/{ELEM_TYPE}/$*/g' $< > $@ 81 | 82 | clear: 83 | rm fil/*.fil 84 | -------------------------------------------------------------------------------- /examples/Displacement_visualization/model_results.fil: -------------------------------------------------------------------------------- 1 | *I 19I 41921A6.19-1 A03-Sep-2A021 A17:07:05I 14I 19D 2.500000000000000D+00* 2 | I 18I 41900I 11ACAX4 I 11I 12I 15I 14*I 18I 41900I 12ACAX4 I 12I 13I 16I 1 3 | 5*I 18I 41900I 13ACAX4 I 14I 15I 18I 17*I 18I 41900I 14ACAX4 I 15I 16I 19I 4 | 18*I 15I 41901I 11D 0.000000000000000D+00D 0.000000000000000D+00*I 15I 41901I 1 5 | 2D 2.500000000000000D+00D 0.000000000000000D+00*I 15I 41901I 13D 5.0000000000000 6 | 00D+00D 0.000000000000000D+00*I 15I 41901I 14D 0.000000000000000D+00D 2.50000000 7 | 0000000D+00*I 15I 41901I 15D 2.500000000000000D+00D 2.500000000000000D+00*I 15I 8 | 41901I 16D 5.000000000000000D+00D 2.500000000000000D+00*I 15I 41901I 17D 0.00000 9 | 0000000000D+00D 5.000000000000000D+00*I 15I 41901I 18D 2.500000000000000D+00D 5. 10 | 000000000000000D+00*I 15I 41901I 19D 5.000000000000000D+00D 5.000000000000000D+0 11 | 0*I 17I 41933A 2I 11I 12I 13I 14*I 15I 41933A 3I 11I 13*I 15I 41933A 12 | 4I 11I 12*I 15I 41933A 5I 13I 14*I 15I 41933A 7I 13I 14*I 212 13 | I 41931A 2I 11I 12I 13I 14I 15I 16I 17I 18I 19*I 16I 41931A 3I 11I 1 14 | 4I 17*I 16I 41931A 4I 11I 12I 13*I 15I 41940I 11AASSEMBLYA_SURF-1 *I 16I 4 15 | 1940I 12AASSEMBLYA_PART-1-A1_SET-1 *I 15I 41940I 13AASSEMBLYA_SET-1 *I 15I 4194 16 | 0I 14AASSEMBLYA_SET-2 *I 16I 41940I 15AASSEMBLYA__SURF-1A_S3 *I 15I 41940I 17 | 16AMATERIALA-1 *I 15I 41940I 17A DSL- L A A *I 15I 41940I 18AANTIALIAA 18 | SING *I 235I 41902I 11I 12I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 1 19 | 0I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10*I 212I 20 | 41922A A A A A A A A A 21 | A *I 12I 42001 22 | 23 | *I 17I 41501A 1I 14I 11I 12I 10*I 17I 41502I 13I 13I 12I 17I 18*I 17I 4150 24 | 2I 14I 13I 12I 18I 19*I 12I 42001 25 | 26 | *I 223I 42000D 1.000000000000000D+00D 1.000000000000000D+00D 0.000000000000000D+ 27 | 00D 0.000000000000000D+00I 11I 11I 11I 10D 0.000000000000000D+00D 0.000000000000 28 | 000D+00D 1.000000000000000D+00A A A A A A 29 | A A A A *I 14I 41911I 11A *I 15I 3101I 11 30 | D 0.000000000000000D+00D 6.544984694978705D-34*I 15I 3101I 12D-3.749999999999995 31 | D-05D 3.926990816987240D-33*I 15I 3101I 13D-7.499999999999994D-05D 3.27249234748 32 | 9370D-33*I 15I 3101I 14D 0.000000000000000D+00D 1.249999999999998D-04*I 15I 3101 33 | I 15D-3.749999999999994D-05D 1.250000000000000D-04*I 15I 3101I 16D-7.49999999999 34 | 9999D-05D 1.250000000000002D-04*I 15I 3101I 17D 0.000000000000000D+00D 2.4999999 35 | 99999994D-04*I 15I 3101I 18D-3.750000000000013D-05D 2.500000000000001D-04*I 15I 36 | 3101I 19D-7.500000000000024D-05D 2.500000000000004D-04*I 12I 42001 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /tests/abaqus/fil/quad_CPS4.fil: -------------------------------------------------------------------------------- 1 | *I 19I 41921A6.23-1 A07-Nov-2A024 A16:49:32I 11I 14D 1.155000000000000D+01* 2 | I 18I 41900I 11ACPS4 I 11I 12I 14I 13*I 15I 41901I 11D 1.000000000000000D-01D 3 | 2.000000000000000D-01*I 15I 41901I 12D 1.290000000000000D+01D 2.000000000000000 4 | D-01*I 15I 41901I 13D 1.000000000000000D-01D 1.050000000000000D+01*I 15I 41901I 5 | 14D 1.290000000000000D+01D 1.050000000000000D+01*I 14I 41933A 1I 11*I 17I 6 | 41931A 1I 11I 12I 13I 14*I 14I 41931A 2I 11*I 14I 41931A 3I 12 7 | *I 15I 41931A 4I 13I 14*I 18I 41940I 11AASSEMBLYA_TEST_INASTANCE_SAET-TEST 8 | _APART *I 16I 41940I 12AASSEMBLYA_SET_BC_A1 *I 16I 41940I 13AASSEMBLYA_ 9 | SET_BC_A2 *I 16I 41940I 14AASSEMBLYA_SET_LOAAD *I 15I 41940I 15ATEST 10 | -MATAERIAL *I 15I 41940I 16A NODES_ZAERO_AREA*I 15I 41940I 17AANTIALIAASING 11 | *I 15I 41940I 18Atest-steAp *I 236I 41902I 11I 12I 10I 10I 10I 10I 10I 10 12 | I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10 13 | I 10I 10I 10I 10I 10I 10*I 212I 41922ATest eleAments ofA the typAe CPS4 wAith qu 14 | adA shape A A A A *I 12I 42001 15 | 16 | *I 223I 42000D 1.000000000000000D+00D 1.000000000000000D+00D 0.000000000000000D+ 17 | 00D 0.000000000000000D+00I 11I 11I 11I 10D 0.000000000000000D+00D 0.000000000000 18 | 000D+00D 1.000000000000000D+00A A A A A A 19 | A A A A *I 15I 41911I 10A ACPS4 *I 211 20 | I 11I 11I 11I 10I 10A I 12I 11I 10I 10*I 15I 211D 0.000000000000000D+00D 21 | 1.562500000000000D+03D-1.734723475976807D-14*I 15I 221D-3.906250000000001D-03D 1 22 | .562500000000000D-02D-4.336808689942018D-19*I 14I 18D 2.804958277186368D+00D 2.3 23 | 76646113673406D+00*I 211I 11I 11I 12I 10I 10A I 12I 11I 10I 10*I 15I 211D 24 | -1.705302565824240D-13D 1.562500000000000D+03D 5.204170427930421D-14*I 15I 221D- 25 | 3.906250000000001D-03D 1.562500000000000D-02D 1.301042606982605D-18*I 14I 18D 1. 26 | 019504172281363D+01D 2.376646113673406D+00*I 211I 11I 11I 13I 10I 10A I 1 27 | 2I 11I 10I 10*I 15I 211D 5.684341886080801D-14D 1.562500000000000D+03D-1.3877787 28 | 80781446D-13*I 15I 221D-3.906250000000000D-03D 1.562500000000000D-02D-3.46944695 29 | 1953614D-18*I 14I 18D 2.804958277186368D+00D 8.323353886326595D+00*I 211I 11I 11 30 | I 14I 10I 10A I 12I 11I 10I 10*I 15I 211D-5.684341886080801D-14D 1.562500 31 | 000000000D+03D-6.938893903907228D-14*I 15I 221D-3.906250000000000D-03D 1.5625000 32 | 00000000D-02D-1.734723475976807D-18*I 14I 18D 1.019504172281363D+01D 8.323353886 33 | 326595D+00*I 14I 41911I 11A *I 15I 3107I 11D 1.000000000000000D-01D 2.000 34 | 000000000000D-01*I 15I 3107I 12D 1.290000000000000D+01D 2.000000000000000D-01*I 35 | 15I 3107I 13D 1.000000000000000D-01D 1.050000000000000D+01*I 15I 3107I 14D 1.290 36 | 000000000000D+01D 1.050000000000000D+01*I 15I 3101I 11D 0.000000000000000D+00D 9 37 | .999999999999999D-34*I 15I 3101I 12D-5.000000000000002D-02D 1.000000000000000D-3 38 | 3*I 15I 3101I 13D 0.000000000000000D+00D 1.609375000000000D-01*I 15I 3101I 14D-4 39 | .999999999999999D-02D 1.609375000000000D-01*I 12I 42001 40 | 41 | -------------------------------------------------------------------------------- /tests/abaqus/fil/quad_CPS4I.fil: -------------------------------------------------------------------------------- 1 | *I 19I 41921A6.23-1 A07-Nov-2A024 A16:49:27I 11I 14D 1.155000000000000D+01* 2 | I 18I 41900I 11ACPS4I I 11I 12I 14I 13*I 15I 41901I 11D 1.000000000000000D-01D 3 | 2.000000000000000D-01*I 15I 41901I 12D 1.290000000000000D+01D 2.000000000000000 4 | D-01*I 15I 41901I 13D 1.000000000000000D-01D 1.050000000000000D+01*I 15I 41901I 5 | 14D 1.290000000000000D+01D 1.050000000000000D+01*I 14I 41933A 1I 11*I 17I 6 | 41931A 1I 11I 12I 13I 14*I 14I 41931A 2I 11*I 14I 41931A 3I 12 7 | *I 15I 41931A 4I 13I 14*I 18I 41940I 11AASSEMBLYA_TEST_INASTANCE_SAET-TEST 8 | _APART *I 16I 41940I 12AASSEMBLYA_SET_BC_A1 *I 16I 41940I 13AASSEMBLYA_ 9 | SET_BC_A2 *I 16I 41940I 14AASSEMBLYA_SET_LOAAD *I 15I 41940I 15ATEST 10 | -MATAERIAL *I 15I 41940I 16A NODES_ZAERO_AREA*I 15I 41940I 17AANTIALIAASING 11 | *I 15I 41940I 18Atest-steAp *I 236I 41902I 11I 12I 10I 10I 10I 10I 10I 10 12 | I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10 13 | I 10I 10I 10I 10I 10I 10*I 212I 41922ATest eleAments ofA the typAe CPS4I Awith q 14 | uaAd shape A A A A *I 12I 42001 15 | 16 | *I 223I 42000D 1.000000000000000D+00D 1.000000000000000D+00D 0.000000000000000D+ 17 | 00D 0.000000000000000D+00I 11I 11I 11I 10D 0.000000000000000D+00D 0.000000000000 18 | 000D+00D 1.000000000000000D+00A A A A A A 19 | A A A A *I 15I 41911I 10A ACPS4I *I 211 20 | I 11I 11I 11I 10I 10A I 12I 11I 10I 10*I 15I 211D 0.000000000000000D+00D 21 | 1.562500000000000D+03D-1.037004815102622D-14*I 15I 221D-3.906249999999999D-03D 1 22 | .562499999999999D-02D-2.592512037756554D-19*I 14I 18D 2.804958277186368D+00D 2.3 23 | 76646113673406D+00*I 211I 11I 11I 12I 10I 10A I 12I 11I 10I 10*I 15I 211D 24 | -1.136868377216160D-13D 1.562500000000000D+03D-6.977186608741855D-15*I 15I 221D- 25 | 3.906250000000000D-03D 1.562499999999999D-02D-1.744296652185464D-19*I 14I 18D 1. 26 | 019504172281363D+01D 2.376646113673406D+00*I 211I 11I 11I 13I 10I 10A I 1 27 | 2I 11I 10I 10*I 15I 211D 2.273736754432321D-13D 1.562500000000000D+03D 5.9018890 28 | 88804607D-14*I 15I 221D-3.906249999999997D-03D 1.562500000000000D-02D 1.47547227 29 | 2201152D-18*I 14I 18D 2.804958277186368D+00D 8.323353886326595D+00*I 211I 11I 11 30 | I 14I 10I 10A I 12I 11I 10I 10*I 15I 211D 1.705302565824240D-13D 1.562500 31 | 000000000D+03D 7.975898719009849D-14*I 15I 221D-3.906249999999998D-03D 1.5625000 32 | 00000000D-02D 1.993974679752462D-18*I 14I 18D 1.019504172281363D+01D 8.323353886 33 | 326595D+00*I 14I 41911I 11A *I 15I 3107I 11D 1.000000000000000D-01D 2.000 34 | 000000000000D-01*I 15I 3107I 12D 1.290000000000000D+01D 2.000000000000000D-01*I 35 | 15I 3107I 13D 1.000000000000000D-01D 1.050000000000000D+01*I 15I 3107I 14D 1.290 36 | 000000000000D+01D 1.050000000000000D+01*I 15I 3101I 11D 0.000000000000000D+00D 9 37 | .999999999999997D-34*I 15I 3101I 12D-5.000000000000000D-02D 9.999999999999999D-3 38 | 4*I 15I 3101I 13D-2.775557561562891D-17D 1.609375000000000D-01*I 15I 3101I 14D-4 39 | .999999999999999D-02D 1.609375000000000D-01*I 12I 42001 40 | 41 | -------------------------------------------------------------------------------- /src/pybaqus/nodes.py: -------------------------------------------------------------------------------- 1 | """ 2 | Definition of node objects. 3 | """ 4 | 5 | import numpy as np 6 | 7 | 8 | class Node: 9 | """Define a node in the finite element model. 10 | 11 | Parameters 12 | ---------- 13 | x : float 14 | y : float 15 | z : float 16 | num : float 17 | 18 | """ 19 | 20 | def __init__(self, num: int, model): 21 | self._num: int = num 22 | self.model = model 23 | self._in_elements = None 24 | 25 | @property 26 | def x(self): 27 | return self._x 28 | 29 | @property 30 | def y(self): 31 | return self._y 32 | 33 | @property 34 | def z(self): 35 | return self._z 36 | 37 | @property 38 | def rx(self): 39 | return self._rx 40 | 41 | @property 42 | def ry(self): 43 | return self._ry 44 | 45 | @property 46 | def rz(self): 47 | return self._rz 48 | 49 | @property 50 | def coords(self): 51 | return self._get_coords() 52 | 53 | @property 54 | def in_elements(self): 55 | return self._in_elements 56 | 57 | @in_elements.setter 58 | def in_elements(self, x): 59 | self._in_elements = x 60 | 61 | def _get_coords(self): 62 | print("This method needs to be redefined in subclass") 63 | return 1 64 | 65 | 66 | class Node2D(Node): 67 | """Two-dimensional node. 68 | 69 | Parameters 70 | ---------- 71 | num : int 72 | ID of the node 73 | dof_map : dict 74 | Dictionary mapping the active DOF to each nodal output position 75 | model : `obj`:Model 76 | Model to which the node belongs to. 77 | *dof : 78 | The values for all degrees of freedom. 79 | 80 | """ 81 | _x: float 82 | _y: float 83 | _rz: float 84 | 85 | def __init__(self, num: int, dof_map, model, *dof): 86 | super().__init__(num, model) 87 | 88 | self._x = dof[dof_map[0] - 1] 89 | self._y = dof[dof_map[1] - 1] 90 | self._rz = dof[dof_map[5] - 1] if dof_map[5] > 0 else np.nan 91 | self._num = num 92 | 93 | def _get_coords(self): 94 | return (self._x, self._y, 0) 95 | 96 | 97 | class Node3D(Node): 98 | """Three-dimensional node. 99 | 100 | Parameters 101 | ---------- 102 | num : int 103 | Number of the node 104 | dof_map : dict 105 | Dictionary mapping the active DOF to each nodal output position 106 | model : `obj`:Model 107 | Model to which the node belongs to. 108 | *dof : 109 | The values for all degree of freedom. 110 | 111 | """ 112 | _x: float 113 | _y: float 114 | _z: float 115 | _rx: float 116 | _ry: float 117 | _rz: float 118 | 119 | def __init__(self, num, dof_map, model, *dof): 120 | super().__init__(num, model) 121 | 122 | self._x = dof[dof_map[0] - 1] 123 | self._y = dof[dof_map[1] - 1] 124 | self._z = dof[dof_map[2] - 1] 125 | self._rx = dof[dof_map[3] - 1] if dof_map[3] > 0 else np.nan 126 | self._ry = dof[dof_map[4] - 1] if dof_map[4] > 0 else np.nan 127 | self._rz = dof[dof_map[5] - 1] if dof_map[5] > 0 else np.nan 128 | self._num = num 129 | 130 | def _get_coords(self): 131 | return (self._x, self._y, self._z) 132 | -------------------------------------------------------------------------------- /tests/test_reader.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from numpy.testing import assert_allclose 3 | 4 | from pybaqus.reader import open_fil, read_records 5 | 6 | 7 | @pytest.fixture 8 | def fil_path_2d(): 9 | return "tests/abaqus/fil/quad_CPE4.fil" 10 | 11 | 12 | @pytest.fixture 13 | def fil_path_3d(): 14 | return "tests/abaqus/fil/hex_C3D8.fil" 15 | 16 | 17 | def test_read_records(fil_path_2d): 18 | records = read_records(fil_path_2d) 19 | assert hasattr(records, "__iter__") # Check if it's an iterator 20 | 21 | 22 | @pytest.mark.parametrize("progress", [False, True]) 23 | def test_open_fil(fil_path_2d, progress, capsys): 24 | result = open_fil(fil_path_2d, progress=progress) 25 | assert result is not None 26 | 27 | captured = capsys.readouterr() 28 | if progress: 29 | assert "Reading records..." in captured.out 30 | assert "Parsing records..." in captured.out 31 | else: 32 | assert captured.out == "" 33 | 34 | 35 | def test_open_fil_nonexistent_file(): 36 | with pytest.raises(FileNotFoundError): 37 | open_fil("nonexistent_file.fil") 38 | 39 | 40 | def test_abaqus_release(fil_path_2d): 41 | model = open_fil(fil_path_2d) 42 | # Check the release 43 | assert model.release["release"] == "6.23-1" 44 | 45 | 46 | def test_heading(fil_path_2d): 47 | model = open_fil(fil_path_2d) 48 | assert model.heading == "Test elements of the type CPE4 with quad shape" 49 | 50 | 51 | def test_model_size(fil_path_2d): 52 | model = open_fil(fil_path_2d) 53 | assert model.size["elements"] == len(model.elements) 54 | assert model.size["nodes"] == len(model.nodes) 55 | 56 | 57 | def test_discontinuous_nodes(): 58 | model = open_fil("tests/abaqus/fil/discontinuous_numbering_2D.fil") 59 | assert model.size["nodes"] == len(model.nodes) 60 | 61 | 62 | def test_parse_node_2d(fil_path_2d): 63 | model = open_fil(fil_path_2d) 64 | n1 = model.nodes[1] 65 | n2 = model.nodes[2] 66 | n3 = model.nodes[3] 67 | n4 = model.nodes[4] 68 | 69 | assert_allclose(n1.coords, [0.1, 0.2, 0.0]) 70 | assert_allclose(n2.coords, [12.9, 0.2, 0.0]) 71 | assert_allclose(n3.coords, [0.1, 10.5, 0.0]) 72 | assert_allclose(n4.coords, [12.9, 10.5, 0.0]) 73 | 74 | 75 | def test_parse_node_3d(fil_path_3d): 76 | model = open_fil(fil_path_3d) 77 | n1 = model.nodes[1] 78 | n2 = model.nodes[2] 79 | n3 = model.nodes[3] 80 | n4 = model.nodes[4] 81 | n5 = model.nodes[5] 82 | n6 = model.nodes[6] 83 | n7 = model.nodes[7] 84 | n8 = model.nodes[8] 85 | 86 | assert_allclose(n1.coords, [0.0, 0.0, 0.0]) 87 | assert_allclose(n2.coords, [10.0, 0.0, 0.0]) 88 | assert_allclose(n3.coords, [0.0, 20.0, 0.0]) 89 | assert_allclose(n4.coords, [10.0, 20.0, 0.0]) 90 | assert_allclose(n5.coords, [0.0, 0.0, 30.0]) 91 | assert_allclose(n6.coords, [10.0, 0.0, 30.0]) 92 | assert_allclose(n7.coords, [0.0, 20.0, 30.0]) 93 | assert_allclose(n8.coords, [10.0, 20.0, 30.0]) 94 | 95 | 96 | @pytest.mark.parametrize( 97 | "file_path,expected_record_count", 98 | [ 99 | ("tests/abaqus/fil/quad_CPE4.fil", 50), 100 | ], 101 | ) 102 | def test_read_records_count(file_path, expected_record_count): 103 | records = list(read_records(file_path)) 104 | assert len(records) == expected_record_count 105 | -------------------------------------------------------------------------------- /tests/abaqus/fil/quad_CPE4.fil: -------------------------------------------------------------------------------- 1 | *I 19I 41921A6.23-1 A07-Nov-2A024 A16:49:23I 11I 14D 1.155000000000000D+01* 2 | I 18I 41900I 11ACPE4 I 11I 12I 14I 13*I 15I 41901I 11D 1.000000000000000D-01D 3 | 2.000000000000000D-01*I 15I 41901I 12D 1.290000000000000D+01D 2.000000000000000 4 | D-01*I 15I 41901I 13D 1.000000000000000D-01D 1.050000000000000D+01*I 15I 41901I 5 | 14D 1.290000000000000D+01D 1.050000000000000D+01*I 14I 41933A 1I 11*I 17I 6 | 41931A 1I 11I 12I 13I 14*I 14I 41931A 2I 11*I 14I 41931A 3I 12 7 | *I 15I 41931A 4I 13I 14*I 18I 41940I 11AASSEMBLYA_TEST_INASTANCE_SAET-TEST 8 | _APART *I 16I 41940I 12AASSEMBLYA_SET_BC_A1 *I 16I 41940I 13AASSEMBLYA_ 9 | SET_BC_A2 *I 16I 41940I 14AASSEMBLYA_SET_LOAAD *I 15I 41940I 15ATEST 10 | -MATAERIAL *I 15I 41940I 16A NODES_ZAERO_AREA*I 15I 41940I 17AANTIALIAASING 11 | *I 15I 41940I 18Atest-steAp *I 236I 41902I 11I 12I 10I 10I 10I 10I 10I 10 12 | I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10 13 | I 10I 10I 10I 10I 10I 10*I 212I 41922ATest eleAments ofA the typAe CPE4 wAith qu 14 | adA shape A A A A *I 12I 42001 15 | 16 | *I 223I 42000D 1.000000000000000D+00D 1.000000000000000D+00D 0.000000000000000D+ 17 | 00D 0.000000000000000D+00I 11I 11I 11I 10D 0.000000000000000D+00D 0.000000000000 18 | 000D+00D 1.000000000000000D+00A A A A A A 19 | A A A A *I 15I 41911I 10A ACPE4 *I 211 20 | I 11I 11I 11I 10I 10A I 13I 11I 10I 10*I 16I 211D 1.136868377216160D-13D 21 | 1.562500000000000D+03D 3.906249999999999D+02D-5.204170427930421D-14*I 16I 221D-4 22 | .882812499999998D-03D 1.464843750000000D-02D 0.000000000000000D+00D-1.3010426069 23 | 82605D-18*I 14I 18D 2.804958277186368D+00D 2.376646113673406D+00*I 211I 11I 11I 24 | 12I 10I 10A I 13I 11I 10I 10*I 16I 211D-1.136868377216160D-13D 1.56250000 25 | 0000000D+03D 3.906249999999999D+02D-8.673617379884035D-14*I 16I 221D-4.882812500 26 | 000000D-03D 1.464843750000000D-02D 0.000000000000000D+00D-2.168404344971009D-18* 27 | I 14I 18D 1.019504172281363D+01D 2.376646113673406D+00*I 211I 11I 11I 13I 10I 10 28 | A I 13I 11I 10I 10*I 16I 211D 1.136868377216160D-13D 1.562500000000000D+0 29 | 3D 3.906249999999999D+02D-6.938893903907228D-14*I 16I 221D-4.882812499999998D-03 30 | D 1.464843750000000D-02D 0.000000000000000D+00D-1.734723475976807D-18*I 14I 18D 31 | 2.804958277186368D+00D 8.323353886326595D+00*I 211I 11I 11I 14I 10I 10A I 32 | 13I 11I 10I 10*I 16I 211D 1.136868377216160D-13D 1.562500000000000D+03D 3.90624 33 | 9999999999D+02D-6.938893903907228D-14*I 16I 221D-4.882812499999998D-03D 1.464843 34 | 750000000D-02D 0.000000000000000D+00D-1.734723475976807D-18*I 14I 18D 1.01950417 35 | 2281363D+01D 8.323353886326595D+00*I 14I 41911I 11A *I 15I 3107I 11D 1.00 36 | 0000000000000D-01D 2.000000000000000D-01*I 15I 3107I 12D 1.290000000000000D+01D 37 | 2.000000000000000D-01*I 15I 3107I 13D 1.000000000000000D-01D 1.050000000000000D+ 38 | 01*I 15I 3107I 14D 1.290000000000000D+01D 1.050000000000000D+01*I 15I 3101I 11D 39 | 0.000000000000000D+00D 9.999999999999997D-34*I 15I 3101I 12D-6.249999999999999D- 40 | 02D 1.000000000000000D-33*I 15I 3101I 13D-1.387778780781446D-17D 1.5087890624999 41 | 99D-01*I 15I 3101I 14D-6.250000000000001D-02D 1.508789062499999D-01*I 12I 42001 42 | 43 | -------------------------------------------------------------------------------- /tests/abaqus/fil/quad_CPE4H.fil: -------------------------------------------------------------------------------- 1 | *I 19I 41921A6.23-1 A07-Nov-2A024 A16:49:19I 11I 14D 1.155000000000000D+01* 2 | I 18I 41900I 11ACPE4H I 11I 12I 14I 13*I 15I 41901I 11D 1.000000000000000D-01D 3 | 2.000000000000000D-01*I 15I 41901I 12D 1.290000000000000D+01D 2.000000000000000 4 | D-01*I 15I 41901I 13D 1.000000000000000D-01D 1.050000000000000D+01*I 15I 41901I 5 | 14D 1.290000000000000D+01D 1.050000000000000D+01*I 14I 41933A 1I 11*I 17I 6 | 41931A 1I 11I 12I 13I 14*I 14I 41931A 2I 11*I 14I 41931A 3I 12 7 | *I 15I 41931A 4I 13I 14*I 18I 41940I 11AASSEMBLYA_TEST_INASTANCE_SAET-TEST 8 | _APART *I 16I 41940I 12AASSEMBLYA_SET_BC_A1 *I 16I 41940I 13AASSEMBLYA_ 9 | SET_BC_A2 *I 16I 41940I 14AASSEMBLYA_SET_LOAAD *I 15I 41940I 15ATEST 10 | -MATAERIAL *I 15I 41940I 16A NODES_ZAERO_AREA*I 15I 41940I 17AANTIALIAASING 11 | *I 15I 41940I 18Atest-steAp *I 236I 41902I 11I 12I 10I 10I 10I 10I 10I 10 12 | I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10 13 | I 10I 10I 10I 10I 10I 10*I 212I 41922ATest eleAments ofA the typAe CPE4H Awith q 14 | uaAd shape A A A A *I 12I 42001 15 | 16 | *I 223I 42000D 1.000000000000000D+00D 1.000000000000000D+00D 0.000000000000000D+ 17 | 00D 0.000000000000000D+00I 11I 11I 11I 10D 0.000000000000000D+00D 0.000000000000 18 | 000D+00D 1.000000000000000D+00A A A A A A 19 | A A A A *I 15I 41911I 10A ACPE4H *I 211 20 | I 11I 11I 11I 10I 10A I 13I 11I 10I 10*I 16I 211D-1.136867240347783D-13D 21 | 1.562500000000000D+03D 3.906249999999999D+02D 1.040834085586084D-13*I 16I 221D-4 22 | .882812500000000D-03D 1.464843750000000D-02D 0.000000000000000D+00D 2.6020852139 23 | 65211D-18*I 14I 18D 2.804958277186368D+00D 2.376646113673406D+00*I 211I 11I 11I 24 | 12I 10I 10A I 13I 11I 10I 10*I 16I 211D-1.136867240347783D-13D 1.56250000 25 | 0000000D+03D 3.906249999999999D+02D 0.000000000000000D+00*I 16I 221D-4.882812500 26 | 000000D-03D 1.464843750000000D-02D 0.000000000000000D+00D 0.000000000000000D+00* 27 | I 14I 18D 1.019504172281363D+01D 2.376646113673406D+00*I 211I 11I 11I 13I 10I 10 28 | A I 13I 11I 10I 10*I 16I 211D-1.136866103479406D-13D 1.562500000000000D+0 29 | 3D 3.906249999999999D+02D 1.387778780781446D-13*I 16I 221D-4.882812500000000D-03 30 | D 1.464843750000000D-02D 0.000000000000000D+00D 3.469446951953614D-18*I 14I 18D 31 | 2.804958277186368D+00D 8.323353886326595D+00*I 211I 11I 11I 14I 10I 10A I 32 | 13I 11I 10I 10*I 16I 211D 2.273736754497703D-19D 1.562500000000000D+03D 3.90624 33 | 9999999998D+02D-6.938893903907228D-14*I 16I 221D-4.882812499999998D-03D 1.464843 34 | 750000000D-02D 0.000000000000000D+00D-1.734723475976807D-18*I 14I 18D 1.01950417 35 | 2281363D+01D 8.323353886326595D+00*I 14I 41911I 11A *I 15I 3107I 11D 1.00 36 | 0000000000000D-01D 2.000000000000000D-01*I 15I 3107I 12D 1.290000000000000D+01D 37 | 2.000000000000000D-01*I 15I 3107I 13D 1.000000000000000D-01D 1.050000000000000D+ 38 | 01*I 15I 3107I 14D 1.290000000000000D+01D 1.050000000000000D+01*I 15I 3101I 11D 39 | 0.000000000000000D+00D 1.000000000000000D-33*I 15I 3101I 12D-6.249999999999997D- 40 | 02D 1.000000000000000D-33*I 15I 3101I 13D 4.163336342344337D-17D 1.5087890625000 41 | 00D-01*I 15I 3101I 14D-6.249999999999999D-02D 1.508789062500000D-01*I 12I 42001 42 | 43 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Pybaqus 2 | 3 | Pybaqus is a python library to import the output files generated by [Abaqus][1] in the ASCII `*.fil` format, and create a [VTK][2] object from the data. 4 | The results can then be analyzed in pure python (i.e. no Abaqus licence needed) with the great tools provided by [PyVista][3]. 5 | 6 | # Features 7 | 8 | Pybaqus is in a very early development stage. 9 | Therefore, there are still many unimplemented functionalities. 10 | However, basic operations like importing the mesh and the nodal and element results is implemented and can be used for some analysis. 11 | 12 | The following features are either already implemented or planned: 13 | 14 | - [x] Import 2D meshes 15 | - [x] Import 3D meshes 16 | - [x] Import nodal results 17 | - [x] Import element results 18 | - [x] Element and node sets 19 | - [x] Extrapolate element results from Gaussian points to nodes _(implemented for some elements)_ 20 | - [ ] Import history output 21 | - [x] Compute stresses along paths 22 | - [ ] Compute section forces and moments 23 | - [ ] Documentation 24 | 25 | # Installation 26 | 27 | ``` 28 | pip install pybaqus 29 | ``` 30 | 31 | # Quick-start 32 | 33 | The first thing you need is to tell Abaqus that you want an ASCII `*.fil` result file. 34 | To get that you need to write the following lines in your `*.inp` file, within the step definition (before the `*End Step` command) e.g.: 35 | 36 | ``` 37 | ... 38 | *FILE FORMAT, ASCII 39 | *EL FILE, DIRECTIONS=YES 40 | S, E, COORD 41 | *NODE FILE 42 | COORD, U 43 | 44 | *End Step 45 | ... 46 | ``` 47 | 48 | You can specify different output variables (as long as they are available for the elements you are using, of course). 49 | After submitting your model you will get a `*.fil` file. 50 | This is the file you need, as it can be imported with Pybaqus. 51 | 52 | Import the `*.fil` file like this: 53 | 54 | ```python 55 | from pybaqus import open_fil 56 | 57 | res = open_fil("your_result.fil") 58 | 59 | ``` 60 | 61 | Great! 62 | That was it. :) 63 | 64 | Now you have your results as a VTK object, wrapped by PyVista, and there's nothing that can get in your way to analyze your results with pure python. 65 | 66 | ### Plot the mesh 67 | 68 | ```python 69 | import pyvista as pv 70 | 71 | mesh = res.get_mesh() 72 | 73 | 74 | plot = pv.Plotter() 75 | plot.add_mesh(mesh, show_edges=True, color="white") 76 | plot.view_xy() 77 | plot.show() 78 | ``` 79 | 80 | ![Mesh](examples/mesh_hole.png) 81 | 82 | Cool! But something's missing there. Colors! 83 | We can plot some of our results like this: 84 | 85 | ```python 86 | mesh = res.get_deformed_mesh(step=1, inc=1, scale=3) 87 | s2 = res.get_nodal_result(var="S2", step=1, inc=1) 88 | mesh.point_data["S2"] = s2 89 | 90 | plot = pv.Plotter() 91 | plot.add_mesh(mesh, show_edges=True, color="white", 92 | scalars="S2", show_scalar_bar=True) 93 | plot.view_xy() 94 | plot.show() 95 | ``` 96 | 97 | ![Mesh](examples/mesh_results.png) 98 | 99 | That's it! 100 | Since the API is still under development, some of these functions might change. 101 | 102 | And now you can de whatever you want with your results in python. 103 | Have fun! 104 | 105 | [1]: https://www.3ds.com/products-services/simulia/products/abaqus/ 106 | [2]: https://vtk.org/ 107 | [3]: https://www.pyvista.org/ 108 | 109 | # Acknowledgments 110 | 111 | This project has benefited from funding from the Deutsche Forschungsgemeinschaft (DFG, German Research Foundation) under Germany's Excellence Strategy – EXC 2120/1 – 390831618 [IntCDC](https://www.intcdc.uni-stuttgart.de) 112 | -------------------------------------------------------------------------------- /tests/abaqus/fil/discontinuous_numbering_2D.fil: -------------------------------------------------------------------------------- 1 | *I 19I 41921A6.23-1 A06-Nov-2A024 A17:00:24I 12I 16D 1.000000000000000D+01* 2 | I 18I 41900I 11ACPS4 I 11I 12I 14I 13*I 18I 41900I 12ACPS4 I 12I 15I 16I 1 3 | 4*I 15I 41901I 11D 0.000000000000000D+00D 0.000000000000000D+00*I 15I 41901I 12D 4 | 1.000000000000000D+01D 0.000000000000000D+00*I 15I 41901I 13D 0.000000000000000 5 | D+00D 1.000000000000000D+01*I 15I 41901I 14D 1.000000000000000D+01D 1.0000000000 6 | 00000D+01*I 15I 41901I 15D 2.000000000000000D+01D 0.000000000000000D+00*I 15I 41 7 | 901I 16D 2.000000000000000D+01D 1.000000000000000D+01*I 15I 41933A 1I 11I 8 | 12*I 19I 41931A 1I 11I 12I 13I 14I 15I 16*I 14I 41931A 2I 11*I 15I 4 9 | 1931A 3I 12I 15*I 16I 41931A 4I 13I 14I 16*I 18I 41940I 11AASSEMBLYA 10 | _TEST_INASTANCE_SAET-TEST_APART *I 16I 41940I 12AASSEMBLYA_SET_BC_A1 *I 11 | 16I 41940I 13AASSEMBLYA_SET_BC_A2 *I 16I 41940I 14AASSEMBLYA_SET_LOAAD 12 | *I 15I 41940I 15ATEST-MATAERIAL *I 15I 41940I 16A NODES_ZAERO_AREA*I 15I 4 13 | 1940I 17AANTIALIAASING *I 15I 41940I 18Atest-steAp *I 236I 41902I 11I 1 14 | 2I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 1 15 | 0I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10*I 212I 41922AAn exampAle with 16 | Aa dicontAinuous nAumberingA of the Anodes A A A *I 12I 4 17 | 2001 18 | 19 | *I 223I 42000D 1.000000000000000D+00D 1.000000000000000D+00D 0.000000000000000D+ 20 | 00D 0.000000000000000D+00I 11I 11I 11I 10D 0.000000000000000D+00D 0.000000000000 21 | 000D+00D 1.000000000000000D+00A A A A A A 22 | A A A A *I 15I 41911I 10A ACPS4 *I 211 23 | I 11I 11I 11I 10I 10A I 12I 11I 10I 10*I 15I 211D 3.040590759368534D+02D 24 | 1.983236745685358D+03D 8.101633269356097D+01*I 15I 221D-1.917501104844859D-03D 1 25 | .907221976701144D-02D 2.025408317339024D-03*I 14I 18D 2.113248654051850D+00D 2.1 26 | 13248654051850D+00*I 211I 11I 11I 12I 10I 10A I 12I 11I 10I 10*I 15I 211D 27 | 8.687402169624292D+01D 1.114496528722915D+03D-6.558357891885011D+01*I 15I 221D- 28 | 1.917501104844859D-03D 1.092778023298855D-02D-1.639589472971253D-03*I 14I 18D 7. 29 | 886751345948150D+00D 2.113248654051850D+00*I 211I 11I 11I 13I 10I 10A I 1 30 | 2I 11I 10I 10*I 15I 211D-8.687402169624272D+01D 1.885503471277083D+03D-2.4476124 31 | 86673548D+02*I 15I 221D-5.582498895155136D-03D 1.907221976701144D-02D-6.11903121 32 | 6683869D-03*I 14I 18D 2.113248654051850D+00D 7.886751345948150D+00*I 211I 11I 11 33 | I 14I 10I 10A I 12I 11I 10I 10*I 15I 211D-3.040590759368533D+02D 1.016763 34 | 254314641D+03D-3.913611602797658D+02*I 15I 221D-5.582498895155136D-03D 1.0927780 35 | 23298855D-02D-9.784029006994146D-03*I 14I 18D 7.886751345948150D+00D 7.886751345 36 | 948150D+00*I 211I 11I 12I 11I 10I 10A I 12I 11I 10I 10*I 15I 211D 8.68740 37 | 2169624275D+01D 1.114496528722916D+03D 6.558357891885016D+01*I 15I 221D-1.917501 38 | 104844862D-03D 1.092778023298855D-02D 1.639589472971254D-03*I 14I 18D 1.21132486 39 | 5405185D+01D 2.113248654051850D+00*I 211I 11I 12I 12I 10I 10A I 12I 11I 1 40 | 0I 10*I 15I 211D 3.040590759368533D+02D 1.983236745685358D+03D-8.101633269356073 41 | D+01*I 15I 221D-1.917501104844862D-03D 1.907221976701145D-02D-2.025408317339018D 42 | -03*I 14I 18D 1.788675134594815D+01D 2.113248654051850D+00*I 211I 11I 12I 13I 10 43 | I 10A I 12I 11I 10I 10*I 15I 211D-3.040590759368530D+02D 1.01676325431464 44 | 2D+03D 3.913611602797661D+02*I 15I 221D-5.582498895155134D-03D 1.092778023298855 45 | D-02D 9.784029006994151D-03*I 14I 18D 1.211324865405185D+01D 7.886751345948150D+ 46 | 00*I 211I 11I 12I 14I 10I 10A I 12I 11I 10I 10*I 15I 211D-8.6874021696242 47 | 49D+01D 1.885503471277084D+03D 2.447612486673552D+02*I 15I 221D-5.58249889515513 48 | 4D-03D 1.907221976701144D-02D 6.119031216683880D-03*I 14I 18D 1.788675134594815D 49 | +01D 7.886751345948150D+00*I 14I 41911I 11A *I 15I 3107I 11D 0.0000000000 50 | 00000D+00D 0.000000000000000D+00*I 15I 3107I 12D 1.000000000000000D+01D 0.000000 51 | 000000000D+00*I 15I 3107I 13D 0.000000000000000D+00D 1.000000000000000D+01*I 15I 52 | 3107I 14D 1.000000000000000D+01D 1.000000000000000D+01*I 15I 3107I 15D 2.000000 53 | 000000000D+01D 0.000000000000000D+00*I 15I 3107I 16D 2.000000000000000D+01D 1.00 54 | 0000000000000D+01*I 15I 3101I 11D 0.000000000000000D+00D 8.448275862068973D-34*I 55 | 15I 3101I 12D-5.760188087774877D-03D 1.310344827586205D-33*I 15I 3101I 13D 6.34 56 | 7962382445019D-02D 2.205329153605006D-01*I 15I 3101I 14D-5.760188087774881D-03D 57 | 7.946708463949922D-02*I 15I 3101I 15D-1.152037617554980D-02D 8.448275862068973D- 58 | 34*I 15I 3101I 16D-7.499999999999991D-02D 2.205329153605007D-01*I 12I 42001 59 | 60 | -------------------------------------------------------------------------------- /src/pybaqus/faces.py: -------------------------------------------------------------------------------- 1 | """ 2 | Implementation of faces 3 | """ 4 | import numpy as np 5 | from copy import copy 6 | 7 | from pyvista import UnstructuredGrid 8 | 9 | 10 | class Surface: 11 | """Surface object. 12 | 13 | Parameters 14 | ---------- 15 | name : str 16 | Name of the surface 17 | 18 | """ 19 | 20 | def __init__(self, name, dimension, model): 21 | self._name = name 22 | self._model = model 23 | self._faces: list = list() 24 | self._type: str = None 25 | dimension_map = {1: "1-D", 2: "2-D", 3: "3-D", 4: "Axysymmetric"} 26 | self._dimension = dimension_map[dimension] 27 | self._mesh = None 28 | 29 | @property 30 | def dimension(self): 31 | return self._dimension 32 | 33 | @property 34 | def mesh(self): 35 | """TODO: Docstring for mesh. 36 | Returns 37 | ------- 38 | TODO 39 | 40 | """ 41 | if self._mesh is not None: 42 | return copy(self._mesh) 43 | else: 44 | return copy(self._gen_mesh()) 45 | 46 | def __str__(self): 47 | text = ( 48 | f"{self._type} surface '{self._name}'\n" 49 | + f"Dimension: {self._dimension}\n" 50 | + f"Number of faces: {len(self._faces)}\n" 51 | ) 52 | return text 53 | 54 | def add_face(self, face): 55 | """Add a face to the surface 56 | 57 | Parameters 58 | ---------- 59 | face : `obj`:Face 60 | 61 | """ 62 | self._faces.append(face) 63 | 64 | def get_cells(self): 65 | """Get face geometries of the surface. 66 | 67 | Parameters 68 | ---------- 69 | step : TODO 70 | inc : TODO 71 | scale : TODO 72 | 73 | Returns 74 | ------- 75 | TODO 76 | 77 | """ 78 | faces = self._faces 79 | 80 | u_nodes = self.get_used_nodes() 81 | 82 | # Remap node keys 83 | sorted_nodes = sorted(u_nodes.keys()) 84 | new_keys = {old: new for new, old in enumerate(sorted_nodes)} 85 | new_nodes = np.asarray([u_nodes[k].coords for k in sorted_nodes]) 86 | 87 | list_nodes = [y for fi in faces for y in self._surf_data(fi, new_keys)] 88 | elem_type = [fi.element_type for fi in faces] 89 | 90 | ar_cells = np.asarray(list_nodes) 91 | ar_elem_type = np.asarray(elem_type, np.int8) 92 | 93 | return ar_cells, ar_elem_type, new_nodes 94 | 95 | def get_used_nodes(self): 96 | """Get the nodes belonging to the surface. 97 | 98 | Returns 99 | ------- 100 | dict : 101 | Dictionary with the used nodes. 102 | 103 | """ 104 | node_list = [] 105 | for fi in self._faces: 106 | node_list += fi.get_nodes() 107 | 108 | # nodes = np.unique(np.asarray([fi.get_nodes() for fi in self._faces])) 109 | nodes = np.unique(np.asarray(node_list)) 110 | 111 | all_nodes = self._model.nodes 112 | used_nodes = {k: all_nodes[k] for k in nodes} 113 | 114 | return used_nodes 115 | 116 | def _gen_mesh(self): 117 | """Construct the mesh of the finite element model 118 | 119 | Returns 120 | ------- 121 | mesh : mesh 122 | VTK mesh unstructured grid 123 | 124 | """ 125 | cells, elem_t, nodes = self.get_cells() 126 | 127 | mesh = UnstructuredGrid(cells, elem_t, nodes) 128 | 129 | self._mesh = mesh 130 | 131 | return self._mesh 132 | 133 | def _surf_data(self, face, new_keys): 134 | """Get nodes, offset and element type of face element. 135 | 136 | Parameters 137 | ---------- 138 | face : TODO 139 | 140 | Returns 141 | ------- 142 | TODO 143 | 144 | """ 145 | global_nodes = face.get_nodes() 146 | local_nodes = [new_keys[k] for k in global_nodes] 147 | 148 | nodes = [face._n_nodes] + local_nodes 149 | return nodes 150 | 151 | 152 | class RigidSurface(Surface): 153 | """Rigid surface object. 154 | 155 | Parameters 156 | ---------- 157 | name : str 158 | Label of the surface. 159 | dimension : int 160 | Dimension of the surface. 161 | ref_point : int 162 | Label of the reference node for the rigid surface. 163 | 164 | """ 165 | 166 | def __init__(self, name, dimension, model, ref_point): 167 | super().__init__(name, dimension, model) 168 | self._ref_point = ref_point 169 | self._type = "Rigid" 170 | 171 | 172 | class DeformableSurface(Surface): 173 | """Deformable surface object. 174 | 175 | Parameters 176 | ---------- 177 | name : str 178 | Label of the surface. 179 | dimension : int 180 | Dimension of the surface. 181 | master_surfaces : list 182 | List of the master surface names. 183 | 184 | """ 185 | 186 | def __init__(self, name, dimension, model, master_surfaces): 187 | super().__init__(name, dimension, model) 188 | self._master_surfaces = master_surfaces 189 | self._type = "Deformable" 190 | 191 | 192 | class Face: 193 | """Defines an element Face object. 194 | 195 | Parameters 196 | ---------- 197 | element : int 198 | Index of the underlying element of the face. 199 | face : int 200 | Number of the internal face of the element. 201 | nodes : list 202 | List of node labels comprising the face. 203 | 204 | """ 205 | 206 | def __init__(self, element, face, nodes): 207 | self._element = element 208 | self._face = face 209 | self._nodes = nodes 210 | self._n_nodes = len(nodes) 211 | 212 | def get_nodes(self): 213 | """Get the vertices of the face.""" 214 | # return self._element.get_face(self._face) 215 | return self._nodes 216 | 217 | @property 218 | def element_type(self): 219 | """Return the element type of the surface""" 220 | return self._element.get_face_shape(self._face) 221 | -------------------------------------------------------------------------------- /tests/abaqus/fil/hex_C3D8.fil: -------------------------------------------------------------------------------- 1 | *I 19I 41921A6.23-1 A07-Nov-2A024 A16:50:01I 11I 18D 2.000000000000000D+01* 2 | I 212I 41900I 11AC3D8 I 11I 12I 14I 13I 15I 16I 18I 17*I 16I 41901I 11D 0.000 3 | 000000000000D+00D 0.000000000000000D+00D 0.000000000000000D+00*I 16I 41901I 12D 4 | 1.000000000000000D+01D 0.000000000000000D+00D 0.000000000000000D+00*I 16I 41901I 5 | 13D 0.000000000000000D+00D 2.000000000000000D+01D 0.000000000000000D+00*I 16I 4 6 | 1901I 14D 1.000000000000000D+01D 2.000000000000000D+01D 0.000000000000000D+00*I 7 | 16I 41901I 15D 0.000000000000000D+00D 0.000000000000000D+00D 3.000000000000000D+ 8 | 01*I 16I 41901I 16D 1.000000000000000D+01D 0.000000000000000D+00D 3.000000000000 9 | 000D+01*I 16I 41901I 17D 0.000000000000000D+00D 2.000000000000000D+01D 3.0000000 10 | 00000000D+01*I 16I 41901I 18D 1.000000000000000D+01D 2.000000000000000D+01D 3.00 11 | 0000000000000D+01*I 14I 41933A 1I 11*I 211I 41931A 1I 11I 12I 13I 14 12 | I 15I 16I 17I 18*I 14I 41931A 2I 11*I 14I 41931A 3I 14*I 15I 41931A 13 | 4I 12I 13*I 17I 41931A 5I 15I 16I 17I 18*I 18I 41940I 11AASSEMBLYA_T 14 | EST_INASTANCE_SAET-TEST_APART *I 16I 41940I 12AASSEMBLYA_SET_BC_A1 *I 1 15 | 6I 41940I 13AASSEMBLYA_SET_BC_A2 *I 16I 41940I 14AASSEMBLYA_SET_BC_A3 16 | *I 16I 41940I 15AASSEMBLYA_SET_LOAAD *I 15I 41940I 16ATEST-MATAERIAL * 17 | I 15I 41940I 17A NODES_ZAERO_AREA*I 15I 41940I 18AANTIALIAASING *I 15I 41940I 18 | 19Atest-steAp *I 236I 41902I 11I 12I 13I 10I 10I 10I 10I 10I 10I 10I 10I 19 | 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 10I 20 | 10I 10I 10*I 212I 41922ATest eleAments ofA the typAe C3D8 wAith hex Ashape A 21 | A A A *I 12I 42001 22 | 23 | *I 223I 42000D 1.000000000000000D+00D 1.000000000000000D+00D 0.000000000000000D+ 24 | 00D 0.000000000000000D+00I 11I 11I 11I 10D 0.000000000000000D+00D 0.000000000000 25 | 000D+00D 1.000000000000000D+00A A A A A A 26 | A A A A *I 15I 41911I 10A AC3D8 *I 211 27 | I 11I 11I 11I 10I 10A I 13I 13I 10I 10*I 18I 211D-1.781822547468652D+00D 28 | 6.695266022198746D+00D 3.419889858603343D+00D 2.352460259453869D+01D 3.390710085 29 | 233756D+00D 5.263709925322325D+01*I 18I 221D-4.310611517669174D-05D 6.2857491944 30 | 15074D-05D 2.191528989920819D-05D 5.881150648634673D-04D 8.476775213084390D-05D 31 | 1.315927481330581D-03*I 15I 18D 2.113248654051850D+00D 4.226497308103700D+00D 6. 32 | 339745962155551D+00*I 211I 11I 11I 12I 10I 10A I 13I 13I 10I 10*I 18I 211 33 | D 6.233695131126897D+00D-7.866032752617214D+00D 9.965670954823707D+00D 1.6900025 34 | 80064974D+01D-6.373150486473761D-01D 4.624428329149067D+01*I 18I 221D 5.70878558 35 | 0575274D-05D-1.191587427410487D-04D 1.037375536019629D-04D 4.225006450162435D-04 36 | D-1.593287621618440D-05D 1.156107082287267D-03*I 15I 18D 7.886751345948150D+00D 37 | 4.226497308103700D+00D 6.339745962155551D+00*I 211I 11I 11I 13I 10I 10A I 38 | 13I 13I 10I 10*I 18I 211D 1.832621858498404D+00D 3.680801760372159D+01D-3.03073 39 | 0612888661D+01D 9.477861411271750D-01D 1.482217881608042D+00D 3.634044174958341D 40 | +01*I 18I 221D 2.074439897896586D-06D 4.392668867131864D-04D-3.996746599444160D- 41 | 04D 2.369465352817937D-05D 3.705544704020106D-05D 9.085110437395851D-04*I 15I 18 42 | D 2.113248654051850D+00D 1.577350269189630D+01D 6.339745962155551D+00*I 211I 11I 43 | 11I 14I 10I 10A I 13I 13I 10I 10*I 18I 211D 9.243827519048548D+00D 2.164 44 | 240681086022D+01D-2.255290099657536D+01D-5.676790652761770D+00D-2.54580725227307 45 | 2D+00D 3.917839501861997D+01*I 18I 221D 9.471451065477332D-05D 2.496967518024192 46 | D-04D-3.027445957905255D-04D-1.419197663190443D-04D-6.364518130682679D-05D 9.794 47 | 598754654994D-04*I 15I 18D 7.886751345948150D+00D 1.577350269189630D+01D 6.33974 48 | 5962155551D+00*I 211I 11I 11I 15I 10I 10A I 13I 13I 10I 10*I 18I 211D-1.5 49 | 97265579353357D+00D-1.784199871731870D+01D 2.777259763000544D+01D-1.502696526725 50 | 256D+00D 1.186105211670976D+00D 4.757138576463654D+00*I 18I 221D-4.0799153075250 51 | 42D-05D-2.438583172998172D-04D 3.263241370417345D-04D-3.756741316813140D-05D 2.9 52 | 65263029177441D-05D 1.189284644115913D-04*I 15I 18D 2.113248654051850D+00D 4.226 53 | 497308103701D+00D 2.366025403784445D+01*I 211I 11I 11I 16I 10I 10A I 13I 54 | 13I 10I 10*I 18I 211D-2.812517131526940D+00D-1.394175903059635D+01D 2.5087609495 55 | 45666D+01D-8.127273320614188D+00D-2.841919922210168D+00D-2.759753446667217D-01*I 56 | 18I 221D-5.598979747742020D-05D-1.951053212157879D-04D 2.927617853598749D-04D-2 57 | .031818330153547D-04D-7.104799805525419D-05D-6.899383616668043D-06*I 15I 18D 7.8 58 | 86751345948150D+00D 4.226497308103701D+00D 2.366025403784445D+01*I 211I 11I 11I 59 | 17I 10I 10A I 13I 13I 10I 10*I 18I 211D 2.017178826613782D+00D 1.22707528 60 | 6420409D+01D-5.954598357484542D+00D 3.612794712170679D+00D 1.997017089249683D+00 61 | D-1.153951892717619D+01*I 18I 221D 4.381401999338939D-06D 1.325510774692178D-04D 62 | -9.526581280189011D-05D 9.031986780426698D-05D 4.992542723124206D-05D-2.88487973 63 | 1794047D-04*I 15I 18D 2.113248654051850D+00D 1.577350269189630D+01D 2.3660254037 64 | 84445D+01*I 211I 11I 11I 18I 10I 10A I 13I 13I 10I 10*I 18I 211D 1.976152 65 | 563947737D-01D 1.556668053288104D+01D-7.430962455942454D+00D-3.011782081718227D+ 66 | 00D-2.031008044631431D+00D-7.341863617537410D+00*I 18I 221D-1.836314262839872D-0 67 | 5D 1.737501733276796D-04D-1.137203640326141D-04D-7.529455204295567D-05D-5.077520 68 | 111578578D-05D-1.835465904384352D-04*I 15I 18D 7.886751345948150D+00D 1.57735026 69 | 9189630D+01D 2.366025403784445D+01*I 14I 41911I 11A *I 16I 3107I 11D 0.00 70 | 0000000000000D+00D 0.000000000000000D+00D 0.000000000000000D+00*I 16I 3107I 12D 71 | 1.000000000000000D+01D 0.000000000000000D+00D 0.000000000000000D+00*I 16I 3107I 72 | 13D 0.000000000000000D+00D 2.000000000000000D+01D 0.000000000000000D+00*I 16I 31 73 | 07I 14D 1.000000000000000D+01D 2.000000000000000D+01D 0.000000000000000D+00*I 16 74 | I 3107I 15D 0.000000000000000D+00D 0.000000000000000D+00D 3.000000000000000D+01* 75 | I 16I 3107I 16D 1.000000000000000D+01D 0.000000000000000D+00D 3.000000000000000D 76 | +01*I 16I 3107I 17D 0.000000000000000D+00D 2.000000000000000D+01D 3.000000000000 77 | 000D+01*I 16I 3107I 18D 1.000000000000000D+01D 2.000000000000000D+01D 3.00000000 78 | 0000000D+01*I 16I 3101I 11D 1.000000000000018D-33D 4.000000000000032D-33D 3.0950 79 | 53244505093D-33*I 16I 3101I 12D 5.484804966181764D-03D 1.164481342587608D-02D 2. 80 | 904946755494933D-33*I 16I 3101I 13D 2.522468266468996D-04D 1.591976089707215D-02 81 | D-3.095053244505061D-33*I 16I 3101I 14D-9.999999999999978D-34D 1.339947113345505 82 | D-02D-2.904946755494958D-33*I 16I 3101I 15D 5.051174020143923D-03D 5.99146192441 83 | 8786D-02D 2.050606210644612D-02*I 16I 3101I 16D 5.303420846790804D-03D 5.8219353 84 | 82219540D-02D 1.912043191745783D-02*I 16I 3101I 17D 1.531191921647853D-03D 5.027 85 | 534615199374D-02D-2.139020844790947D-02*I 16I 3101I 18D-3.953613044533890D-03D 5 86 | .518420830973840D-02D-2.073628557599447D-02*I 12I 42001 87 | 88 | -------------------------------------------------------------------------------- /src/pybaqus/elements.py: -------------------------------------------------------------------------------- 1 | """ 2 | Definitions for the different element types. 3 | 4 | The different Abaqus elements are represented by the corresponding VTK cell 5 | types defined in [1]. Since typically different Abaqus element types are 6 | represented by the same geometry, a class for each geometry (or better said, 7 | VTK cell type) is created, e.g. Quad or Triangle. All these classes inherit 8 | from the `Element` class, where generic functions are defined. 9 | 10 | Each Abaqus element is associated to one of these classes. The number of 11 | integration points is an attribute of each object, which is set for each 12 | element during the importing process of the Abaqus model. The correspondance 13 | of each Abaqus element with the correct Element class is done via the 14 | dictionary `ELEMENTS`, which contains the Abaqus reference code of the element 15 | as key (e.g. `CPS4`) and the corresponding Element class as value. Similarly, 16 | the number of integration points for each Abaqus element is defined in the 17 | dictionary `N_INT_PNTS`. 18 | 19 | # Adding new elements 20 | 21 | To add support for a new element, the Abaqus element code has to be added to 22 | both dictionaries `ELEMENTS` and `N_INT_PNTS` with the corresponding 23 | information. Additionally, it should be ensured that the corresponding class 24 | has implemented the function `_extrapol_matrix` for the number of integration 25 | points of the element (see e.g. the class `Quad`). 26 | 27 | # Interpolation schemes used in Abaqus 28 | 29 | The interpolation schemes used for each element are defined in the Abaqus guide, 30 | under the following sections: 31 | 32 | * Theory 33 | * Elements 34 | * Continuum elements 35 | * Solid isoparametric quadrilaterals and hexahedra 36 | * Triangular, tetrahedral, and wedge elements 37 | * Membrane and truss elements 38 | * Truss elements 39 | 40 | # References 41 | 42 | [1] https://kitware.github.io/vtk-examples/site/VTKBook/05Chapter5/#54-cell-types 43 | 44 | """ 45 | import numpy as np 46 | import vtk 47 | 48 | 49 | class Element: 50 | """Define a general element of a finite element model. 51 | 52 | Subclasses must be implemented for each actual element. 53 | 54 | Parameters 55 | ---------- 56 | num : int 57 | model : `obj`:Model 58 | 59 | """ 60 | def __init__(self, num, model, code): 61 | """TODO: to be defined. 62 | 63 | Parameters 64 | ---------- 65 | id : TODO 66 | 67 | 68 | """ 69 | self._num: int = num 70 | self._nodes: list = None 71 | self._n_nodes: int = None 72 | self._connectivity: list = None 73 | self._elem_code: str = code 74 | self._model = model 75 | self._elem_type = None 76 | self._faces: dict = dict() 77 | self._face_shape: dict = dict() 78 | self._n_integ_points: int = None 79 | self.map_node = np.vectorize(self._map_node) 80 | 81 | @property 82 | def elem_type(self): 83 | return self._elem_type 84 | 85 | @property 86 | def elem_code(self): 87 | return self._elem_code 88 | 89 | @property 90 | def model(self): 91 | return self._model 92 | 93 | @property 94 | def num(self): 95 | return self._num 96 | 97 | def get_nodes(self): 98 | return self._nodes 99 | 100 | def get_nodes_coords(self): 101 | """Get coordinates of nodes 102 | 103 | Returns 104 | ------- 105 | TODO 106 | 107 | """ 108 | all_nodes = self._model.nodes 109 | nodes = [all_nodes[n].coords for n in self._nodes] 110 | 111 | return nodes 112 | 113 | def get_cell(self, kmap=None): 114 | """Assemble cell array. 115 | 116 | Parameters 117 | ---------- 118 | kmap : dict 119 | Map origianl node ids to new id 120 | 121 | """ 122 | # Get nodes 123 | nodes = np.asarray(self._nodes) 124 | 125 | if kmap: 126 | nodes = self.map_node(kmap, nodes) 127 | 128 | nodes -= 1 129 | 130 | cell = np.asarray([self._n_nodes, *nodes], dtype=int) 131 | 132 | return cell 133 | 134 | def _map_node(self, kmap, old_id): 135 | """Map an old id to anew id. 136 | 137 | Parameters 138 | ---------- 139 | old_id : TODO 140 | new_id : TODO 141 | 142 | Returns 143 | ------- 144 | TODO 145 | 146 | """ 147 | return kmap[old_id] 148 | 149 | def get_face(self, face): 150 | """Get a specific face of the element. 151 | 152 | Parameters 153 | ---------- 154 | face : TODO 155 | 156 | Returns 157 | ------- 158 | TODO 159 | 160 | """ 161 | face = self._faces[face] 162 | 163 | return face 164 | 165 | def get_face_shape(self, face): 166 | """TODO: Docstring for get_face_shape. 167 | 168 | Parameters 169 | ---------- 170 | face : int 171 | Number of the face. 172 | 173 | Returns 174 | ------- 175 | vtk_shape : 176 | The correct shape of the face. 177 | 178 | """ 179 | return self._face_shape[face] 180 | 181 | @property 182 | def n_integ_points(self): 183 | return self._n_integ_points 184 | 185 | @n_integ_points.setter 186 | def n_integ_points(self, val): 187 | self._n_integ_points = val 188 | 189 | def extrapolate_to_nodes(self, s_int): 190 | """Extrapolate results computed on integration points to the nodes. 191 | 192 | Parameters 193 | ---------- 194 | s_int : array 195 | Results on the integration points. (Order according to Abaqus definition.) 196 | 197 | Returns 198 | ------- 199 | array 200 | 201 | """ 202 | e_matrix = self._extrapol_matrix() 203 | s_n = e_matrix @ s_int 204 | return s_n, self._nodes 205 | 206 | def _extrapol_matrix(self): 207 | """Extrapolation matrix used to compute result variables at nodes.""" 208 | 209 | e = self._elem_type 210 | print(f"Extrapolation matrix for element {e} needs to be defined.") 211 | 212 | return 0 213 | 214 | 215 | class Quad(Element): 216 | """4-node rectangular element.""" 217 | def __init__(self, n1, n2, n3, n4, num, model, code): 218 | super().__init__(num, model, code) 219 | self._n_nodes = 4 220 | self._nodes = [n1, n2, n3, n4] 221 | self._elem_type = vtk.VTK_QUAD 222 | 223 | # Define faces connectivity 224 | self._faces = { 225 | 1: [0, 1], 226 | 2: [1, 2], 227 | 3: [2, 3], 228 | 4: [3, 0], 229 | 7: [0, 1, 2, 3], 230 | 8: [3, 2, 1, 0], 231 | } 232 | self._face_shape = { 233 | 1: vtk.VTK_LINE, 234 | 2: vtk.VTK_LINE, 235 | 3: vtk.VTK_LINE, 236 | 4: vtk.VTK_LINE, 237 | 7: vtk.VTK_QUAD, 238 | 8: vtk.VTK_QUAD, 239 | } 240 | 241 | def _extrapol_matrix(self): 242 | """Extrapolation matrix. 243 | 244 | Returns 245 | ------- 246 | TODO 247 | 248 | """ 249 | if self._n_integ_points == 4: 250 | ext_mat = np.asarray([ 251 | [1.8660254, -0.5, 0.1339746, -0.5], 252 | [-0.5, 1.8660254, -0.5, 0.1339746], 253 | [0.1339746, -0.5, 1.8660254, -0.5], 254 | [-0.5, 0.1339746, -0.5, 1.8660254], 255 | ]) 256 | elif self._n_integ_points == 2: 257 | ext_mat = np.asarray([ 258 | [1.0, 0], 259 | [0.0, 1.0], 260 | [0.0, 1.0], 261 | [1.0, 0], 262 | ]) 263 | # One integration point 264 | else: 265 | ext_mat = np.ones((4, 1)) 266 | 267 | return ext_mat 268 | 269 | def N1(self, xi, eta): 270 | """Shape function for node 1.""" 271 | n1 = 0.25 * (1.0 - xi) * (1.0 - eta) 272 | return n1 273 | 274 | def N2(self, xi, eta): 275 | """Shape function for node 2.""" 276 | n2 = 0.25 * (1.0 + xi) * (1.0 - eta) 277 | return n2 278 | 279 | def N3(self, xi, eta): 280 | """Shape function for node 3.""" 281 | n3 = 0.25 * (1.0 + xi) * (1.0 + eta) 282 | return n3 283 | 284 | def N4(self, xi, eta): 285 | """Shape function for node 4.""" 286 | n4 = 0.25 * (1.0 - xi) * (1.0 + eta) 287 | return n4 288 | 289 | 290 | class Triangle(Element): 291 | """3-node triangular element.""" 292 | def __init__(self, n1, n2, n3, num, model, code): 293 | super().__init__(num, model, code) 294 | self._n_nodes = 3 295 | self._nodes = [n1, n2, n3] 296 | self._elem_type = vtk.VTK_TRIANGLE 297 | 298 | # Define faces connectivity 299 | self._faces = {1: [0, 1], 2: [1, 2], 3: [2, 0], 7: [0, 1, 2], 8: [2, 1, 0]} 300 | self._face_shape = { 301 | 1: vtk.VTK_LINE, 302 | 2: vtk.VTK_LINE, 303 | 3: vtk.VTK_LINE, 304 | 7: vtk.VTK_TRIANGLE, 305 | 8: vtk.VTK_TRIANGLE, 306 | } 307 | 308 | def _extrapol_matrix(self): 309 | """Extrapolation matrix. 310 | 311 | Returns 312 | ------- 313 | TODO 314 | 315 | """ 316 | if self._n_integ_points == 1: 317 | ext_mat = np.ones((3, 1)) 318 | else: 319 | ext_mat = None 320 | 321 | return ext_mat 322 | 323 | 324 | class Tetra(Element): 325 | """4 node tetrahedron elements""" 326 | def __init__(self, n1, n2, n3, n4, num, model, code): 327 | super().__init__(num, model, code) 328 | self._n_nodes = 4 329 | self._nodes = [n1, n2, n3, n4] 330 | self._elem_type = vtk.VTK_TETRA 331 | 332 | self._faces = {1: [0, 1, 2], 2: [0, 3, 1], 3: [1, 3, 2], 4: [2, 3, 0]} 333 | self._face_shape = { 334 | 1: vtk.VTK_TRIANGLE, 335 | 2: vtk.VTK_TRIANGLE, 336 | 3: vtk.VTK_TRIANGLE, 337 | } 338 | 339 | 340 | class Pyramid(Element): 341 | """5 node pyramid element.""" 342 | def __init__(self, n1, n2, n3, n4, n5, num, model, code): 343 | super().__init__(num, model, code) 344 | self._n_nodes = 5 345 | self._nodes = [n1, n2, n3, n4, n5] 346 | self._elem_type = vtk.VTK_PYRAMID 347 | 348 | # Define faces connectivity 349 | self._faces = { 350 | 1: [0, 1, 2, 3], 351 | 2: [0, 4, 1], 352 | 3: [1, 4, 2], 353 | 4: [2, 4, 3], 354 | 5: [3, 4, 0], 355 | } 356 | self._face_shape = { 357 | 1: vtk.VTK_QUAD, 358 | 2: vtk.VTK_TRIANGLE, 359 | 3: vtk.VTK_TRIANGLE, 360 | 4: vtk.VTK_TRIANGLE, 361 | } 362 | 363 | 364 | class Wedge(Element): 365 | """6 node triangular prism element.""" 366 | def __init__(self, n1, n2, n3, n4, n5, n6, num, model, code): 367 | super().__init__(num, model, code) 368 | self._n_nodes = 6 369 | self._nodes = [n1, n2, n3, n4, n5, n6] 370 | self._elem_type = vtk.VTK_WEDGE 371 | 372 | # Define faces connectivity 373 | self._faces = { 374 | 1: [0, 1, 2], 375 | 2: [3, 5, 4], 376 | 3: [0, 3, 4, 1], 377 | 4: [1, 4, 5, 2], 378 | 5: [2, 5, 3, 0], 379 | } 380 | self._face_shape = { 381 | 1: vtk.VTK_TRIANGLE, 382 | 2: vtk.VTK_TRIANGLE, 383 | 3: vtk.VTK_QUAD, 384 | 4: vtk.VTK_QUAD, 385 | 5: vtk.VTK_QUAD, 386 | } 387 | 388 | def _extrapol_matrix(self): 389 | """Extrapolation matrix. 390 | 391 | Returns 392 | ------- 393 | TODO 394 | 395 | """ 396 | if self._n_integ_points == 2: 397 | ext_mat = np.asarray([ 398 | [1.3660254037844386, -0.3660254037844386], 399 | [1.3660254037844386, -0.3660254037844386], 400 | [1.3660254037844386, -0.3660254037844386], 401 | [-0.3660254037844386, 1.3660254037844386], 402 | [-0.3660254037844386, 1.3660254037844386], 403 | [-0.3660254037844386, 1.3660254037844386], 404 | ]) 405 | # One integration point 406 | else: 407 | ext_mat = np.ones((1, 1)) 408 | 409 | return ext_mat 410 | 411 | 412 | class Hexahedron(Element): 413 | """8 node brick element.""" 414 | def __init__(self, n1, n2, n3, n4, n5, n6, n7, n8, num, model, code): 415 | super().__init__(num, model, code) 416 | self._n_nodes = 8 417 | self._nodes = [n1, n2, n3, n4, n5, n6, n7, n8] 418 | self._elem_type = vtk.VTK_HEXAHEDRON 419 | 420 | # Define faces connectivity 421 | self._faces = { 422 | 1: [0, 1, 2, 3], 423 | 2: [4, 7, 6, 5], 424 | 3: [0, 4, 5, 1], 425 | 4: [1, 5, 6, 2], 426 | 5: [2, 6, 7, 3], 427 | 6: [3, 7, 4, 0], 428 | } 429 | self._face_shape = { 430 | 1: vtk.VTK_QUAD, 431 | 2: vtk.VTK_QUAD, 432 | 3: vtk.VTK_QUAD, 433 | 4: vtk.VTK_QUAD, 434 | 5: vtk.VTK_QUAD, 435 | 6: vtk.VTK_QUAD, 436 | } 437 | 438 | def _extrapol_matrix(self): 439 | """Extrapolation matrix. 440 | 441 | Returns 442 | ------- 443 | TODO 444 | 445 | """ 446 | if self._n_integ_points == 8: 447 | ext_mat = np.asarray([ 448 | [ 449 | 2.549038105676658, -0.6830127018922192, 0.18301270189221927, 450 | -0.6830127018922192, -0.6830127018922192, 0.18301270189221927, 451 | -0.04903810567665795, 0.18301270189221927 452 | ], 453 | [ 454 | -0.6830127018922192, 2.549038105676658, -0.6830127018922192, 455 | 0.18301270189221927, 0.18301270189221927, -0.6830127018922192, 456 | 0.18301270189221927, -0.04903810567665795 457 | ], 458 | [ 459 | -0.6830127018922192, 0.18301270189221927, -0.6830127018922192, 460 | 2.549038105676658, 0.18301270189221927, -0.04903810567665795, 461 | 0.18301270189221927, -0.6830127018922192 462 | ], 463 | [ 464 | 0.18301270189221927, -0.6830127018922192, 2.549038105676658, 465 | -0.6830127018922192, -0.04903810567665795, 0.18301270189221927, 466 | -0.6830127018922192, 0.18301270189221927 467 | ], 468 | [ 469 | -0.6830127018922192, 0.18301270189221927, -0.04903810567665795, 470 | 0.18301270189221927, 2.549038105676658, -0.6830127018922192, 471 | 0.18301270189221927, -0.6830127018922192 472 | ], 473 | [ 474 | 0.18301270189221927, -0.6830127018922192, 0.18301270189221927, 475 | -0.04903810567665795, -0.6830127018922192, 2.549038105676658, 476 | -0.6830127018922192, 0.18301270189221927 477 | ], 478 | [ 479 | 0.18301270189221927, -0.04903810567665795, 0.18301270189221927, 480 | -0.6830127018922192, -0.6830127018922192, 0.18301270189221927, 481 | -0.6830127018922192, 2.549038105676658 482 | ], 483 | [ 484 | -0.04903810567665795, 0.18301270189221927, -0.6830127018922192, 485 | 0.18301270189221927, 0.18301270189221927, -0.6830127018922192, 486 | 2.549038105676658, -0.6830127018922192 487 | ], 488 | ]) 489 | # One integration point 490 | else: 491 | ext_mat = np.ones((8, 1)) 492 | 493 | return ext_mat 494 | 495 | 496 | class LineElement(Element): 497 | """2 node line element.""" 498 | def __init__(self, n1, n2, num, model, code): 499 | super().__init__(num, model, code) 500 | self._n_nodes = 2 501 | self._nodes = [n1, n2] 502 | self._elem_type = vtk.VTK_LINE 503 | 504 | # Define faces connectivity 505 | self._faces = {1: [0, 1], 7: [0, 1], 8: [1, 0]} 506 | self._face_shape = { 507 | 1: vtk.VTK_LINE, 508 | 7: vtk.VTK_LINE, 509 | 8: vtk.VTK_LINE, 510 | } 511 | 512 | def _extrapol_matrix(self): 513 | """Extrapolation matrix.""" 514 | return np.ones((2, 1)) 515 | 516 | 517 | class VertexElement(Element): 518 | """1 node point element.""" 519 | def __init__(self, n1, num, model, code): 520 | super().__init__(num, model, code) 521 | self._n_nodes = 1 522 | self._nodes = [n1] 523 | self._elem_type = vtk.VTK_VERTEX 524 | 525 | 526 | class DistributedCouplingElement(Element): 527 | """N node distributed coupling element.""" 528 | def __init__(self, *nodes, num, model, code): 529 | super().__init__(num, model, code) 530 | self._n_nodes = len(nodes) 531 | self._nodes = nodes 532 | self._elem_type = vtk.VTK_POLY_VERTEX 533 | 534 | 535 | class QuadraticQuad(Element): 536 | """8-node rectangular element.""" 537 | def __init__(self, n1, n2, n3, n4, n5, n6, n7, n8, num, model, code): 538 | super().__init__(num, model, code) 539 | self._n_nodes = 4 540 | self._nodes = [n1, n2, n3, n4, n5, n6, n7, n8] 541 | self._elem_type = vtk.VTK_QUADRATIC_QUAD 542 | 543 | # Define faces connectivity 544 | self._faces = { 545 | 1: [0, 1, 4], 546 | 2: [1, 2, 5], 547 | 3: [2, 3, 6], 548 | 4: [3, 0, 7], 549 | } 550 | self._face_shape = { 551 | 1: vtk.VTK_QUADRATIC_EDGE, 552 | 2: vtk.VTK_QUADRATIC_EDGE, 553 | 3: vtk.VTK_QUADRATIC_EDGE, 554 | 4: vtk.VTK_QUADRATIC_EDGE, 555 | } 556 | 557 | def _extrapol_matrix(self): 558 | """Extrapolation matrix. 559 | 560 | Returns 561 | ------- 562 | array 563 | 564 | """ 565 | ext_mat = np.asarray([ 566 | [ 567 | 1.8660254037844386, -0.4999999999999999, 0.13397459621556132, 568 | -0.4999999999999999, 0.6830127018922193, -0.1830127018922193, 569 | -0.1830127018922193, 0.6830127018922193 570 | ], 571 | [ 572 | -0.4999999999999999, 1.8660254037844386, -0.4999999999999999, 573 | 0.13397459621556132, 0.6830127018922193, 0.6830127018922193, 574 | -0.1830127018922193, -0.1830127018922193 575 | ], 576 | [ 577 | 0.13397459621556132, -0.4999999999999999, 1.8660254037844386, 578 | -0.4999999999999999, -0.1830127018922193, 0.6830127018922193, 579 | 0.6830127018922193, -0.1830127018922193 580 | ], 581 | [ 582 | -0.4999999999999999, 0.13397459621556132, -0.4999999999999999, 583 | 1.8660254037844386, -0.1830127018922193, -0.1830127018922193, 584 | 0.6830127018922193, 0.6830127018922193 585 | ], 586 | ]) 587 | 588 | return ext_mat 589 | 590 | 591 | class QuadraticHexahedron(Element): 592 | """20 node quadratic brick element.""" 593 | def __init__(self, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, 594 | n16, n17, n18, n19, n20, num, model, code): 595 | super().__init__(num, model, code) 596 | self._n_nodes = 20 597 | self._nodes = [ 598 | n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16, n17, n18, 599 | n19, n20 600 | ] 601 | self._elem_type = vtk.VTK_QUADRATIC_HEXAHEDRON 602 | 603 | # Define faces connectivity 604 | self._faces = { 605 | 1: [0, 1, 2, 3, 8, 9, 10, 11], 606 | 2: [4, 7, 6, 5, 15, 14, 13, 12], 607 | 3: [0, 4, 5, 1, 16, 12, 17, 8], 608 | 4: [1, 5, 6, 2, 17, 13, 18, 9], 609 | 5: [2, 6, 7, 3, 18, 14, 19, 10], 610 | 6: [3, 7, 4, 0, 19, 15, 16, 11], 611 | } 612 | self._face_shape = { 613 | 1: vtk.VTK_QUADRATIC_QUAD, 614 | 2: vtk.VTK_QUADRATIC_QUAD, 615 | 3: vtk.VTK_QUADRATIC_QUAD, 616 | 4: vtk.VTK_QUADRATIC_QUAD, 617 | 5: vtk.VTK_QUADRATIC_QUAD, 618 | 6: vtk.VTK_QUADRATIC_QUAD, 619 | } 620 | 621 | 622 | class QuadraticTetra(Element): 623 | """10 node quadratic tetra element.""" 624 | def __init__(self, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, num, model, code): 625 | super().__init__(num, model, code) 626 | self._n_nodes = 10 627 | self._nodes = [n1, n2, n3, n4, n5, n6, n7, n8, n9, n10] 628 | self._elem_type = vtk.VTK_QUADRATIC_TETRA 629 | 630 | # Define faces connectivity 631 | self._faces = { 632 | 1: [0, 1, 2, 4, 5, 6], 633 | 2: [0, 3, 1, 7, 8, 4], 634 | 3: [1, 3, 2, 8, 9, 5], 635 | 4: [2, 3, 0, 9, 7, 6], 636 | } 637 | self._face_shape = { 638 | 1: vtk.VTK_QUADRATIC_TRIANGLE, 639 | 2: vtk.VTK_QUADRATIC_TRIANGLE, 640 | 3: vtk.VTK_QUADRATIC_TRIANGLE, 641 | 4: vtk.VTK_QUADRATIC_TRIANGLE, 642 | } 643 | 644 | 645 | ELEMENTS = { 646 | # Distributed coupling 647 | "IDCOUP3U": DistributedCouplingElement, 648 | "IDCOUP3R": DistributedCouplingElement, 649 | # Rigid 650 | "R2D2": LineElement, 651 | "RB2D2": LineElement, 652 | "R3D3": Triangle, 653 | "R3D4": Quad, 654 | "RB3D2": LineElement, 655 | # Truss elements 656 | "T2D2": LineElement, 657 | "T2D2H": LineElement, 658 | "T3D2": LineElement, 659 | "T3D2H": LineElement, 660 | # Shell elements 661 | "STRI3": Triangle, 662 | "S3": Triangle, 663 | "S3R": Triangle, 664 | "S3RS": Triangle, 665 | "S4": Quad, 666 | "S4R": Quad, 667 | "S4RS": Quad, 668 | "S4RSW": Quad, 669 | "S4R5": Quad, 670 | "S8R": QuadraticQuad, 671 | "S8R5": QuadraticQuad, 672 | # 2D Continuum 673 | "CAX4": Quad, 674 | "CPS4": Quad, 675 | "CPE4": Quad, 676 | "CPE4H": Quad, 677 | "CPS4I": Quad, 678 | "CPS4R": Quad, 679 | "CPE3": Triangle, 680 | "CPE3H": Triangle, 681 | "CPS3": Triangle, 682 | "CPEG3": Triangle, 683 | # 3D Continuum 684 | "C3D4": Tetra, 685 | "C3D4H": Tetra, 686 | "C3D10": QuadraticTetra, 687 | "C3D5": Pyramid, 688 | "C3D6": Wedge, 689 | "C3D6H": Wedge, 690 | "C3D8": Hexahedron, 691 | "C3D8H": Hexahedron, 692 | "C3D8I": Hexahedron, 693 | "C3D8R": Hexahedron, 694 | "C3D8RH": Hexahedron, 695 | "C3D8RS": Hexahedron, 696 | "C3D20R": QuadraticHexahedron, 697 | "CSS8": Hexahedron, 698 | # Cohesive elements 699 | "COH2D4": Quad, 700 | } 701 | 702 | N_INT_PNTS = { 703 | # Distributed coupling 704 | "IDCOUP3U": 0, 705 | "IDCOUP3R": 0, 706 | # Rigid 707 | "R2D2": 0, 708 | "RB2D2": 0, 709 | "R3D3": 0, 710 | "R3D4": 0, 711 | "RB3D2": 0, 712 | # Truss elements 713 | "T2D2": 1, 714 | "T2D2H": 1, 715 | "T3D2": 1, 716 | "T3D2H": 1, 717 | # Shell elements 718 | "STRI3": 3, 719 | "S3": 1, 720 | "S3R": 1, 721 | "S3RS": 1, 722 | "S4": 4, 723 | "S4R": 1, 724 | "S4RS": 1, 725 | "S4RSW": 1, 726 | "S4R5": 1, 727 | "S8R": 4, 728 | "S8R5": 4, 729 | # 2D Continuum 730 | "CAX4": 4, 731 | "CPS4": 4, 732 | "CPE4": 4, 733 | "CPE4H": 4, 734 | "CPS4I": 4, 735 | "CPS4R": 1, 736 | "CPE3": 1, 737 | "CPE3H": 1, 738 | "CPS3": 1, 739 | "CPEG3": 1, 740 | # 3D Continuum 741 | "C3D4": 1, 742 | "C3D4H": 1, 743 | "C3D10": 4, 744 | "C3D6": 2, 745 | "C3D6H": 2, 746 | "C3D8": 8, 747 | "C3D8H": 8, 748 | "C3D8I": 8, 749 | "C3D8R": 1, 750 | "C3D8RS": 1, 751 | "C3D20R": 8, 752 | "CSS8": 8, 753 | # Cohesive elements 754 | "COH2D4": 2, 755 | } 756 | -------------------------------------------------------------------------------- /src/pybaqus/model.py: -------------------------------------------------------------------------------- 1 | """ 2 | Definitions of classes that define the imported model 3 | """ 4 | 5 | from typing import Literal 6 | 7 | import numpy as np 8 | from pyvista import UnstructuredGrid 9 | 10 | from .elements import N_INT_PNTS, Element 11 | from .faces import DeformableSurface, Face, RigidSurface 12 | from .nodes import Node 13 | from .step import Step 14 | 15 | 16 | class Model: 17 | """Class for the model. 18 | 19 | This contains all the information of the model. 20 | 21 | Attributes 22 | ---------- 23 | nodes : dict 24 | elements : dict 25 | element_sets : dict 26 | node_sets : dict 27 | surfaces : dict 28 | 29 | """ 30 | 31 | release: dict[str, str] 32 | _elen: float # typical element length of the model 33 | 34 | def __init__(self): 35 | self.nodes: dict[int, Node] = dict() 36 | self.elements: dict[int, Element] = dict() 37 | self.element_sets: dict = dict() 38 | self.node_sets: dict = dict() 39 | self.surfaces: dict = dict() 40 | self.results: dict = dict() 41 | self.contact_pairs: list = list() 42 | self.metadata: dict = dict() 43 | self.mesh = None 44 | self.elem_output: dict = dict() 45 | self.nodal_output: dict = dict() 46 | self.local_csys: dict = dict() 47 | self.steps: dict = dict() 48 | self._curr_out_step: int = None 49 | self._curr_incr: int = None 50 | self._dimension: int = None 51 | self._status: int = None 52 | 53 | def set_status(self, n): 54 | """Set the SDV number controling the element deletion 55 | 56 | Parameters 57 | ---------- 58 | n : TODO 59 | 60 | Returns 61 | ------- 62 | TODO 63 | 64 | """ 65 | self._status = n 66 | 67 | def add_node(self, node: Node): 68 | self.nodes[node._num] = node 69 | 70 | def add_element(self, element: Element): 71 | self.elements[element.num] = element 72 | 73 | def add_set( 74 | self, name: str, elements: list[int], s_type: Literal["element", "node"] 75 | ): 76 | """Add an element set. 77 | 78 | Parameters 79 | ---------- 80 | name : TODO 81 | 82 | Returns 83 | ------- 84 | list : 85 | List containing the elements of the created set. 86 | 87 | """ 88 | if s_type == "node": 89 | self.node_sets[name] = elements 90 | return self.node_sets[name] 91 | elif s_type == "element": 92 | self.element_sets[name] = elements 93 | return self.element_sets[name] 94 | 95 | def add_deformable_surface(self, name, dimension, master_surf): 96 | """Add a surface to the model. 97 | 98 | Parameters 99 | ---------- 100 | name : TODO 101 | faces : TODO 102 | 103 | """ 104 | if name not in self.surfaces: 105 | self.surfaces[name] = DeformableSurface(name, dimension, self, master_surf) 106 | 107 | def add_rigid_surface(self, name, dimension, ref_point): 108 | """Add a surface to the model. 109 | 110 | Parameters 111 | ---------- 112 | name : TODO 113 | faces : TODO 114 | 115 | """ 116 | if name not in self.surfaces: 117 | self.surfaces[name] = RigidSurface(name, dimension, self, ref_point) 118 | 119 | def add_contact_pair(self, master, slave): 120 | """Add a contact pair to the model. 121 | 122 | Parameters 123 | ---------- 124 | master : str 125 | Name of the surface defining the master surface. 126 | slave : str 127 | Name of the surface defining the slave surface. 128 | 129 | """ 130 | self.contact_pairs += [{"master": master, "slave": slave}] 131 | 132 | def add_face_to_surface(self, surface, face_info): 133 | """Add a face to an existing surface 134 | 135 | Parameters 136 | ---------- 137 | surface : str 138 | Label of the surface to add the facelt to. 139 | face_info : dict 140 | Dictionary with the data to create a Face object. 141 | 142 | """ 143 | elem_n = face_info["element"] 144 | if elem_n == 0: 145 | element = None 146 | else: 147 | element = self.elements[elem_n] 148 | 149 | face = Face(element, face_info["face"], face_info["nodes"]) 150 | self.surfaces[surface].add_face(face) 151 | 152 | def add_elem_output(self, elem, var, data, step, inc, intpnt): 153 | """Add element output data 154 | 155 | Parameters 156 | ---------- 157 | var : TODO 158 | data : TODO 159 | intpnt : int 160 | Integration point number if the results contain integration point data. 161 | TODO: handle elements with different outputs. 162 | 163 | Returns 164 | ------- 165 | TODO 166 | 167 | """ 168 | if var not in self.elem_output[step][inc]: 169 | self.elem_output[step][inc][var] = dict() 170 | 171 | if elem not in self.elem_output[step][inc][var]: 172 | etype = self.elements[elem].elem_code 173 | self.elem_output[step][inc][var][elem] = np.empty( 174 | (N_INT_PNTS[etype], 1), dtype=float 175 | ) 176 | 177 | self.elem_output[step][inc][var][elem][intpnt - 1] = data 178 | 179 | def add_nodal_output(self, node, var, data, step, inc): 180 | """Add nodal output results 181 | 182 | Parameters 183 | ---------- 184 | node : int 185 | Node to which assign the data 186 | var : str 187 | Name of the variable 188 | data : float 189 | Value of the output 190 | 191 | """ 192 | curr_step = self._curr_out_step 193 | curr_inc = self._curr_incr 194 | 195 | if var not in self.nodal_output[curr_step][curr_inc]: 196 | self.nodal_output[curr_step][curr_inc][var] = dict() 197 | 198 | self.nodal_output[step][inc][var][node] = data 199 | 200 | def add_step(self, n, data): 201 | """Add a new step to the output database 202 | 203 | Parameters 204 | ---------- 205 | n : int 206 | Index of the step 207 | data : list 208 | Arguments for the Step object 209 | 210 | Returns 211 | ------- 212 | TODO 213 | 214 | """ 215 | # Add step to model 216 | if n not in self.steps: 217 | self.steps[n] = Step(self, n, data) 218 | 219 | inc_n = data["increment number"] 220 | self._curr_out_step = n 221 | self._curr_incr = inc_n 222 | # Initialize output repository for the current increment in step 223 | self.nodal_output[n] = {inc_n: dict()} 224 | self.elem_output[n] = {inc_n: dict()} 225 | self.local_csys[n] = {inc_n: dict()} 226 | 227 | # Add increment to step 228 | else: 229 | step_time = data["step time"] 230 | load_prop = data["load proportionality"] 231 | time_inc = data["time increment"] 232 | inc_n = data["increment number"] 233 | 234 | # Initialize output repository for the current increment in step 235 | self.nodal_output[n][inc_n] = dict() 236 | self.elem_output[n][inc_n] = dict() 237 | self.local_csys[n][inc_n] = dict() 238 | 239 | self._curr_out_step = data["step number"] 240 | self._curr_incr = data["increment number"] 241 | 242 | self.steps[n].add_increment(inc_n, time_inc, step_time, load_prop) 243 | 244 | def add_local_csys(self, elem, csys, step, inc): 245 | """Add a local coordinate system asociated to the output of an element. 246 | 247 | Parameters 248 | ---------- 249 | elem : int 250 | Identification number of the element to which the local coordinate 251 | system belongs. 252 | csys : arraylike 253 | Coordinate system as a 3x3 or 2x2 array, depending on the dimensionality of 254 | the model. 255 | 256 | """ 257 | self.local_csys[step][inc][elem] = csys 258 | 259 | def add_release_info(self, release, date, time): 260 | self.release = {"release": release, "date": date, "time": time} 261 | 262 | @property 263 | def elen(self): 264 | return self._elen 265 | 266 | @elen.setter 267 | def elen(self, length): 268 | """Typical element length of the model.""" 269 | self._elen = length 270 | 271 | @property 272 | def size(self): 273 | return {"elements": self._n_elements, "nodes": self._n_nodes} 274 | 275 | @size.setter 276 | def size(self, ne): 277 | self._n_elements = ne[0] 278 | self._n_nodes = ne[1] 279 | 280 | @property 281 | def heading(self) -> str: 282 | return self._heading 283 | 284 | @heading.setter 285 | def heading(self, h: str): 286 | self._heading = h 287 | 288 | def get_nodal_result( 289 | self, var, step, inc, node_set=None, elem_set=None, node_ids=None 290 | ): 291 | """Get nodal results 292 | 293 | Parameters 294 | ---------- 295 | var : str 296 | Output variable 297 | step : int 298 | Number of the Abaqus step. 299 | inc : int 300 | Number of the increment. 301 | node_set : str, list 302 | elem_set : str, list 303 | 304 | Returns 305 | ------- 306 | TODO 307 | 308 | """ 309 | # Get the keys of the nodes in the set of nodes 310 | if node_set is not None: 311 | keys = sorted(self.get_nodes_from_set(node_set)) 312 | elem_ids = self.get_elems_from_nodes(keys) 313 | # Get elements belonging to the set 314 | elif elem_set is not None: 315 | elem_ids = self.get_elems_from_set(elem_set) 316 | keys = sorted(self.get_nodes_from_elems(elem_ids)) 317 | elif node_ids is not None: 318 | elem_ids = self.get_elems_from_nodes(node_ids) 319 | keys = sorted(node_ids) 320 | else: 321 | # FIXME: have this variable sorted globally 322 | keys = sorted(list(self.nodes.keys())) 323 | try: 324 | elem_ids = self.elem_output[step][inc][var].keys() 325 | except KeyError: 326 | print( 327 | f"Requested output variable {var} not present as element result of the model." 328 | ) 329 | 330 | if var in self.nodal_output[step][inc]: 331 | results = self.nodal_output[step][inc][var] 332 | elif var in self.elem_output[step][inc]: 333 | results = self._nodal_result_from_elements(var, step, inc, elem_ids) 334 | else: 335 | # FIXME: handle errors properly some day 336 | print("Variable not present") 337 | 338 | list_res = [results[k] for k in keys] 339 | 340 | return np.asarray(list_res) 341 | 342 | def _nodal_result_from_elements(self, var, step, inc, elem_ids): 343 | """Get nodal results from element results by extrapolating. 344 | 345 | Shape functions are used to extrapolate to the nodes. 346 | 347 | Parameters 348 | ---------- 349 | var : str 350 | Result variable. 351 | step : int 352 | Step 353 | inc : int 354 | Increment 355 | 356 | Returns 357 | ------- 358 | array 359 | 360 | """ 361 | keys_out = elem_ids 362 | output = self.elem_output[step][inc][var] 363 | 364 | elements = self.elements 365 | 366 | # FIXME: there are some hacky things here. Try to fix that 367 | nodes = self.nodes 368 | res_nodes = np.zeros(len(nodes) + 1) 369 | counter = np.zeros(len(nodes) + 1) 370 | 371 | for ix in keys_out: 372 | var_i = output[ix] 373 | # Returns extrapolated variables and respective node labels 374 | nodal_i, elem_nodes = elements[ix].extrapolate_to_nodes(var_i) 375 | res_nodes[elem_nodes] += nodal_i.flatten() 376 | counter[elem_nodes] += 1 377 | 378 | # FIXME: Another hacky fix 379 | counter[counter == 0] = np.nan 380 | 381 | result = res_nodes / counter 382 | 383 | # FIXME: output correct size 384 | return result 385 | 386 | def get_local_csys(self, direction, step, inc, elem_set=None): 387 | """Get the local coordinate system of each element (if present). 388 | 389 | Parameters 390 | ---------- 391 | direction : str 392 | Direction of the local coordinate system. 393 | step : int 394 | Step number. 395 | inc : int 396 | Increment number within the step. 397 | elem_set : str, list, optional 398 | Element set. 399 | 400 | Returns 401 | ------- 402 | arraylike : 403 | Array (3xn) or (2xn) depending on the dimensionality of the model. 404 | 405 | """ 406 | if direction == "x": 407 | dim = 0 408 | elif direction == "y": 409 | dim = 1 410 | else: 411 | dim = 2 412 | 413 | # FIXME: have this variable sorted globally 414 | keys = sorted(list(self.elements.keys())) 415 | 416 | # Elements for which the output variable exists 417 | keys_out = set(self.local_csys[step][inc].keys()) 418 | 419 | # Consider "deleted" elements (i.e. elements that have a 100% of damage according 420 | # to the used fracture model) 421 | if self._status is not None: 422 | status = self.elem_output[step][inc][f"SDV{self._status}"] 423 | del_elem = [k for k, v in status.items() if v[0] == 0] 424 | keys_out = [k for k in keys_out if k not in del_elem] 425 | keys = [k for k in keys if k not in del_elem] 426 | 427 | if elem_set is not None: 428 | keys_out, keys = self._map_elem_set_ids_to_output(elem_set, keys, keys_out) 429 | 430 | csys = self.local_csys[step][inc] 431 | 432 | nan_vec = np.ones(self._dimension) * np.nan 433 | 434 | list_res = [csys[k][dim, :] if k in keys_out else nan_vec for k in keys] 435 | 436 | return np.vstack(list_res) 437 | 438 | def _map_elem_set_ids_to_output(self, elem_set, id_elem, id_elem_out): 439 | """Get the keys of the elements in the element set mapped to the output array. 440 | 441 | Parameters 442 | ---------- 443 | elem_set : TODO 444 | id_elem : TODO 445 | id_elem_out : TODO 446 | 447 | Returns 448 | ------- 449 | keys_out : list 450 | keys : list 451 | 452 | """ 453 | set_elements = self.get_elems_from_set(elem_set) 454 | 455 | def filter_elements(elem): 456 | if elem in set_elements: 457 | return True 458 | else: 459 | return False 460 | 461 | keys_out = filter(filter_elements, id_elem) 462 | keys = filter(filter_elements, id_elem_out) 463 | 464 | return keys_out, keys 465 | 466 | def get_time_history_result_from_node(self, var, node_id, steps="all"): 467 | """Get results for a node duiring the whole simulation. 468 | 469 | Parameters 470 | ---------- 471 | var : TODO 472 | node_id : TODO 473 | steps : str, list, int 474 | The steps used to retrieve the results. Default: 'all' 475 | 476 | Returns 477 | ------- 478 | np.asarray : 479 | Results for the given variable `var` 480 | 481 | """ 482 | steps = self.steps.keys() 483 | 484 | # The first step is always zero (FIXME: maybe not always if there are 485 | # prestresses.) 486 | result = [0] 487 | for step in steps: 488 | for inc, val in self.nodal_output[step].items(): 489 | result += [val[var][node_id]] 490 | 491 | return np.asarray(result) 492 | 493 | def get_nodal_vector_result(self, var, step, inc, node_set=None, elem_set=None): 494 | """Get the vector of a variable at each node. 495 | 496 | Parameters 497 | ---------- 498 | var : str 499 | Output variable 500 | step : int 501 | Number of the Abaqus step. 502 | inc : int 503 | Number of the increment. 504 | node_set : str, list 505 | elem_set : str, list 506 | 507 | Returns 508 | ------- 509 | array : 510 | Nx3 array of displacements in each node 511 | 512 | """ 513 | coords = list() 514 | 515 | # Get the keys of the nodes in the set of nodes 516 | if node_set is not None: 517 | keys = sorted(self.get_nodes_from_set(node_set)) 518 | # Get elements belonging to the set 519 | elif elem_set is not None: 520 | elem_ids = self.get_elems_from_set(elem_set) 521 | keys = sorted(self.get_nodes_from_elems(elem_ids)) 522 | else: 523 | nodes = self.nodes 524 | keys = sorted(list(self.nodes.keys())) 525 | 526 | for k in keys: 527 | coords.append(self._get_node_vector_result(k, var, step, inc)) 528 | 529 | coords_ar = np.asarray(coords) 530 | 531 | return coords_ar 532 | 533 | def get_element_result(self, var, step, inc, elem_set=None, elem_id=None): 534 | """Get element results. 535 | 536 | Parameters 537 | ---------- 538 | var : str 539 | Variable that should be retrieved. 540 | step : int 541 | Number of the step. 542 | inc : int 543 | Increment number within the step. 544 | elem_set : str, list 545 | Element set from which the results should be retrieved. 546 | elem_id : int 547 | Number of a single element from which the results should be retrieved. 548 | 549 | Returns 550 | ------- 551 | array : 552 | Results 553 | 554 | """ 555 | # FIXME: have this variable sorted globally 556 | keys = sorted(list(self.elements.keys())) 557 | 558 | # Elements for which the output variable exists 559 | keys_out = set(self.elem_output[step][inc][var].keys()) 560 | 561 | if self._status is not None: 562 | status = self.elem_output[step][inc][f"SDV{self._status}"] 563 | del_elem = [k for k, v in status.items() if v[0] == 0] 564 | keys_out = [k for k in keys_out if k not in del_elem] 565 | keys = [k for k in keys if k not in del_elem] 566 | 567 | if elem_set is not None: 568 | keys_out, keys = self._map_elem_set_ids_to_output(elem_set, keys, keys_out) 569 | 570 | elif elem_id is not None: 571 | set_elements = set(elem_id) 572 | 573 | def filter_elements(elem): 574 | if elem in set_elements: 575 | return True 576 | else: 577 | return False 578 | 579 | keys_out = set(elem_id) 580 | keys = elem_id 581 | 582 | results = self.elem_output[step][inc][var] 583 | 584 | list_res = [np.mean(results[k]) if k in keys_out else np.nan for k in keys] 585 | 586 | ar_results = np.asarray(list_res) 587 | 588 | return ar_results 589 | 590 | def get_surface_result(self, var, step, inc, surf_name): 591 | """Get element result on a given surface. 592 | 593 | Parameters 594 | ---------- 595 | var : str 596 | Output variable. 597 | step : int 598 | Simulation step. 599 | inc : int 600 | Increment within the step. 601 | surface : str 602 | Name of the surface. 603 | 604 | Returns 605 | ------- 606 | TODO 607 | 608 | """ 609 | # Get underlying element numbers 610 | surf = self.surfaces[surf_name] 611 | e_nums = [face._element.num for face in surf._faces] 612 | 613 | # Retrieve element output 614 | out = self.get_element_result(var, step, inc, elem_id=e_nums) 615 | 616 | return out 617 | 618 | def add_metadata(self, metadata): 619 | """Add metadata to the model.""" 620 | self.metadata[metadata[0]] = metadata[1] 621 | 622 | def get_node_coords( 623 | self, node_set=None, elem_set=None, node_id=None, return_map=False 624 | ): 625 | """Get a list with the node coordinates. 626 | 627 | 628 | Parameters 629 | ---------- 630 | node_set : str 631 | node_set 632 | elem_set : str, list 633 | elem_set 634 | node_id : int 635 | node_id 636 | return_map : bool 637 | return_map 638 | 639 | Returns 640 | ------- 641 | coords : array 642 | An array of size (n, 3), where n is the number of nodes 643 | kmap : dict 644 | If either `node_set`, `elem_set` or `node_id` are given and `return_map` is 645 | `True`, then a dictionary is returned mapping the new node ids to the 646 | original node ids. 647 | 648 | """ 649 | nodes = self.nodes 650 | 651 | if node_set is not None: 652 | old_keys = sorted(self.get_nodes_from_set(node_set)) 653 | keys = np.arange(1, len(old_keys) + 1, 1) 654 | # Map new indices to old indices 655 | kmap = {k: ix for k, ix in zip(keys, old_keys)} 656 | elif node_id is not None: 657 | old_keys = sorted([node_id]) 658 | keys = np.arange(1, len(old_keys) + 1, 1) 659 | # Map new indices to old indices 660 | kmap = {k: ix for k, ix in zip(keys, old_keys)} 661 | elif elem_set is not None: 662 | elems = self.get_elems_from_set(elem_set) 663 | old_keys = sorted(self.get_nodes_from_elems(elems)) 664 | keys = np.arange(1, len(old_keys) + 1, 1) 665 | # Map new indices to old indices 666 | kmap = {k: ix for k, ix in zip(keys, old_keys)} 667 | else: 668 | # keys = sorted(list(nodes.keys())) 669 | # kmap = {k: k for k in keys} 670 | # the previous assumes that nodes are from 1 to n without jumps!! 671 | old_keys = sorted(list(nodes.keys())) 672 | keys = np.arange(1, len(old_keys) + 1, 1) 673 | # Map new indices to old indices 674 | kmap = {k: ix for k, ix in zip(keys, old_keys)} 675 | 676 | coords = np.empty((len(keys), 3)) 677 | 678 | for k in keys: 679 | coords[k - 1, :] = nodes[kmap[k]].coords 680 | 681 | coords_ar = np.asarray(coords) 682 | 683 | if return_map: 684 | return coords_ar, kmap 685 | else: 686 | return coords_ar 687 | 688 | def get_deformed_node_coords( 689 | self, step, inc, scale=1, node_id=None, node_set=None, elem_set=None 690 | ): 691 | """Get deformed node coordinates. 692 | 693 | Parameters 694 | ---------- 695 | step : int 696 | Step to get deformations from 697 | inc : int 698 | Index of the increment in the required step. 699 | scale : float 700 | Multiply the deformations by this number. 701 | node_set : str, list 702 | elem_set : str, list 703 | 704 | Returns 705 | ------- 706 | array : 707 | 2D-Array with the node coordinates 708 | 709 | """ 710 | coords, kmap = self.get_node_coords( 711 | node_id=node_id, node_set=node_set, elem_set=elem_set, return_map=True 712 | ) 713 | 714 | for k in range(1, np.shape(coords)[0] + 1, 1): 715 | coords[k - 1, :] += ( 716 | self._get_node_vector_result(kmap[k], "U", step, inc) * scale 717 | ) 718 | 719 | return coords 720 | 721 | def get_cells(self, elem_set=None, status=None): 722 | """Get the definition of cells for all elements. 723 | 724 | The format is the one required by VTK. 725 | 726 | Returns 727 | ------- 728 | cells : array 729 | Cells of each elements 730 | offset : array 731 | Offset for each element 732 | elem_type : array 733 | Array with element types 734 | 735 | """ 736 | elements = self.elements 737 | 738 | # Element deletion is considered here 739 | if status is not None: 740 | 741 | def is_del(n_ele): 742 | if n_ele in status.keys(): 743 | if status[n_ele][0] != 0: 744 | return True 745 | else: 746 | return False 747 | else: 748 | return True 749 | 750 | # Don't consider the deleted elements for mesh 751 | elements = {k: v for k, v in elements.items() if is_del(k)} 752 | 753 | if elem_set is not None: 754 | elem_ids = self.get_elems_from_set(elem_set) 755 | nodes = self.get_nodes_from_elems(elem_ids) 756 | new_node_ids = np.arange(1, len(nodes) + 1, 1) 757 | kmap = {k: ix for k, ix in zip(nodes, new_node_ids)} 758 | elements = {k: elements[k] for k in elem_ids} 759 | else: 760 | node_ids = sorted(list(self.nodes.keys())) 761 | new_node_ids = np.arange(1, len(node_ids) + 1, 1) 762 | # Map new indices to old indices. kmap must be according with get_node_coords 763 | kmap = {ix: k for k, ix in zip(new_node_ids, node_ids)} 764 | 765 | keys = sorted(list(elements.keys())) 766 | 767 | cells = list() 768 | elem_type = list() 769 | 770 | for el_i in keys: 771 | cells.extend(elements[el_i].get_cell(kmap=kmap)) 772 | elem_type.append(elements[el_i]._elem_type) 773 | 774 | ar_cells = np.asarray(cells) 775 | ar_elem_type = np.asarray(elem_type, np.int8) 776 | 777 | return ar_cells, ar_elem_type 778 | 779 | def get_mesh(self, elem_set=None): 780 | """Construct the mesh of the finite element model 781 | 782 | Parameters 783 | ---------- 784 | elem_set : str 785 | Set of elements used to generate the mesh. If none is given, all elements 786 | are used. 787 | 788 | Returns 789 | ------- 790 | mesh : mesh 791 | VTK mesh unstructured grid 792 | 793 | """ 794 | nodes = self.get_node_coords(elem_set=elem_set) 795 | cells, elem_t = self.get_cells(elem_set) 796 | 797 | mesh = UnstructuredGrid(cells, elem_t, nodes) 798 | 799 | self.mesh = mesh 800 | 801 | return self.mesh 802 | 803 | def get_surface(self, name, return_nodes=False, step=None, inc=None, scale=1): 804 | """Get mesh of surface. 805 | 806 | Parameters 807 | ---------- 808 | name : str 809 | Name of the surface 810 | return_nodes : bool (optional) 811 | Whether nodes should be returned separately as a list. 812 | step : int 813 | Step from which the deformation should be taken. 814 | inc : int 815 | Increment from which the deformation should be taken. 816 | scale : float 817 | Scaling factor of the deformation. 818 | 819 | Returns 820 | ------- 821 | mesh : :obj:`UnstructuredGrid` 822 | Mesh representation of the surface. 823 | nodes : list 824 | Nodes corresponding to the mesh. 825 | 826 | """ 827 | surface = self.surfaces[name] 828 | 829 | if return_nodes: 830 | return surface.mesh, surface.get_used_nodes().keys() 831 | else: 832 | return surface.mesh 833 | 834 | def get_deformed_mesh(self, step, inc, scale=1, elem_set=None): 835 | """Construct the deformed mesh in step with scaled deformations. 836 | 837 | Parameters 838 | ---------- 839 | step : int 840 | Index of the needed step 841 | inc : int 842 | Index of the increment within the step 843 | scale : float 844 | Scale to be applied to the deformations 845 | status : int, None 846 | Solution-dependent state variable that controls the element deletion 847 | 848 | Returns 849 | ------- 850 | mesh : mesh 851 | VTK mesh unstructured grid 852 | 853 | """ 854 | nodes = self.get_deformed_node_coords(step, inc, scale, elem_set=elem_set) 855 | 856 | if self._status: 857 | status = self.elem_output[step][inc][f"SDV{self._status}"] 858 | else: 859 | status = None 860 | 861 | cells, elem_t = self.get_cells(elem_set=elem_set, status=status) 862 | 863 | mesh = UnstructuredGrid(cells, elem_t, nodes) 864 | 865 | self.mesh = mesh 866 | 867 | return self.mesh 868 | 869 | def _get_node_vector_result(self, n, var, step, inc): 870 | """Get the displacement vector of the node `n` 871 | 872 | Parameters 873 | ---------- 874 | n : int 875 | The index of the node. 876 | step : int 877 | The step for which the displacement is required. 878 | inc : int 879 | The increment within the required step. 880 | 881 | Returns 882 | ------- 883 | array : 884 | An array with the displacements of the node 885 | 886 | """ 887 | nodal_output = self.nodal_output[step][inc] 888 | 889 | if self._dimension == 3: 890 | u = np.asarray( 891 | [ 892 | nodal_output[f"{var}1"][n], 893 | nodal_output[f"{var}2"][n], 894 | nodal_output[f"{var}3"][n], 895 | ] 896 | ) 897 | else: 898 | u = np.asarray( 899 | [ 900 | nodal_output[f"{var}1"][n], 901 | nodal_output[f"{var}2"][n], 902 | 0, 903 | ] 904 | ) 905 | 906 | return u 907 | 908 | def post_import_actions(self): 909 | """Execute some functions after importing all the records into the model.""" 910 | pass 911 | 912 | def get_elems_from_set(self, elem_set): 913 | """Get the element IDs belonging to an element set. 914 | 915 | Parameters 916 | ---------- 917 | elem_set : str, list 918 | Name of the set or list with names of different sets. 919 | 920 | Returns 921 | ------- 922 | list : 923 | List containing the element IDs present in the set(s). 924 | 925 | """ 926 | if isinstance(elem_set, str): 927 | elem_ids = self.element_sets[elem_set] 928 | # Is list 929 | else: 930 | elem_ids = [] 931 | for set_i in elem_set: 932 | elem_ids += self.element_sets[set_i] 933 | 934 | return set(elem_ids) 935 | 936 | def get_nodes_from_elems(self, elems): 937 | """Get nodal IDs from a list of element IDs. 938 | 939 | Parameters 940 | ---------- 941 | elems : list 942 | 943 | Returns 944 | ------- 945 | TODO 946 | 947 | """ 948 | elements = self.elements 949 | 950 | # Initialize list to store all the nodes 951 | nodes = list() 952 | 953 | for el in elems: 954 | nodes += elements[el]._nodes 955 | 956 | # Remove duplicates 957 | nodes_ar = np.asarray(nodes, dtype=int) 958 | 959 | return np.unique(nodes_ar) 960 | 961 | def get_nodes_from_set(self, node_set): 962 | """Get node IDs belonging to the node set. 963 | 964 | Parameters 965 | ---------- 966 | node_set : str, list 967 | 968 | Returns 969 | ------- 970 | TODO 971 | 972 | """ 973 | if isinstance(node_set, str): 974 | node_ids = self.node_sets[node_set] 975 | # Is list 976 | else: 977 | node_ids = [] 978 | for set_i in node_set: 979 | node_ids += self.node_sets[set_i] 980 | 981 | return node_ids 982 | 983 | def get_elems_from_nodes(self, node_ids): 984 | """Get element IDs from a set of nodes. 985 | 986 | Parameters 987 | ---------- 988 | node_ids : list 989 | 990 | Returns 991 | ------- 992 | TODO 993 | 994 | """ 995 | nodes = self.nodes 996 | elem_ids = list() 997 | 998 | for ni in node_ids: 999 | elem_ids += nodes[ni].in_elements 1000 | 1001 | # Remove duplicates 1002 | elems_ar = np.asarray(elem_ids, dtype=int) 1003 | 1004 | return np.unique(elems_ar) 1005 | 1006 | def __repr__(self): 1007 | n_out = list(self.nodal_output[1][1].keys()) 1008 | e_out = list(self.elem_output[1][1].keys()) 1009 | s = f"""Abaqus result object: 1010 | -------------------- 1011 | Number of nodes: {len(self.nodes):,} 1012 | Number of elements: {len(self.elements):,} 1013 | Number of node sets: {len(self.node_sets):,} 1014 | Number of element sets: {len(self.element_sets):,} 1015 | Nodal output variables: {n_out} 1016 | Element output variables: {e_out} 1017 | """ 1018 | return s 1019 | -------------------------------------------------------------------------------- /src/pybaqus/fil_result.py: -------------------------------------------------------------------------------- 1 | """ 2 | Class for the Fil results 3 | see ABAQUS Analysis User's Manual. FILE OUTPUT FORMAT (ANALYSIS_1.pdf) 4 | """ 5 | import re 6 | import logging 7 | 8 | import numpy as np 9 | from tqdm import tqdm 10 | 11 | from .model import Model 12 | from .nodes import Node2D, Node3D 13 | from .elements import ELEMENTS, N_INT_PNTS 14 | 15 | _log = logging.getLogger(__name__) 16 | 17 | 18 | class FilParser: 19 | """ 20 | Parse and store the data from a *.fil file. 21 | 22 | Parameters 23 | ---------- 24 | records : list(str) 25 | List of the imported records of the *.fil file 26 | 27 | Attributes 28 | ---------- 29 | _elem_out_list : list 30 | List of element/node numbers that correspond to the following output records 31 | 32 | """ 33 | 34 | PARSE_MAP = { 35 | 1: ("_parse_elem_header", []), 36 | 2: ("_parse_elem_output", ["TEMP"]), 37 | 3: ("_parse_elem_output", ["LOADS"]), 38 | 4: ("_parse_elem_output", ["FLUXS"]), 39 | 5: ("_parse_elem_output", ["SDV"]), 40 | 6: ("_parse_elem_output", ["VOIDR"]), 41 | 7: ("_parse_elem_output", ["FOUND"]), 42 | 8: ("_parse_elem_output", ["COORD"]), 43 | 9: ("_parse_elem_output", ["FV"]), 44 | 10: ("_parse_elem_output", ["NFLUX"]), 45 | 11: ("_parse_elem_output", ["S"]), 46 | 12: ("_parse_elem_output", ["SINV"]), 47 | 13: ("_parse_elem_output", ["SF"]), 48 | 14: ("_parse_elem_output", ["ENER"]), 49 | 15: ("_parse_elem_output", ["NFORC"]), 50 | 16: ("_parse_elem_output", ["MSS"]), 51 | 17: ("_parse_elem_output", ["JK"]), 52 | 18: ("_parse_elem_output", ["POR"]), 53 | 19: ("_parse_elem_output", ["ELEN"]), 54 | 21: ("_parse_elem_output", ["E"]), 55 | 22: ("_parse_elem_output", ["PE"]), 56 | 23: ("_parse_elem_output", ["CE"]), 57 | 24: ("_parse_elem_output", ["IE"]), 58 | 25: ("_parse_elem_output", ["EE"]), 59 | 26: ("_parse_elem_output", ["CRACK"]), 60 | 27: ("_parse_elem_output", ["STH"]), 61 | 28: ("_parse_elem_output", ["HFL"]), 62 | 29: ("_parse_elem_output", ["SE"]), 63 | 30: ("_parse_elem_output", ["DG"]), 64 | 31: ("_parse_elem_output", ["CONF"]), 65 | 32: ("_parse_elem_output", ["SJP"]), 66 | 33: ("_parse_elem_output", ["FILM"]), 67 | 34: ("_parse_elem_output", ["RAD"]), 68 | 35: ("_parse_elem_output", ["SAT"]), 69 | 36: ("_parse_elem_output", ["SS"]), 70 | 38: ("_parse_elem_output", ["CONC"]), 71 | 39: ("_parse_elem_output", ["MFL"]), 72 | 40: ("_parse_elem_output", ["GELVR"]), 73 | 42: ("_parse_elem_output", ["SPE"]), 74 | 43: ("_parse_elem_output", ["FLUVR"]), 75 | 44: ("_parse_elem_output", ["CFAILURE"]), 76 | 45: ("_parse_elem_output", ["PEQC"]), 77 | 46: ("_parse_elem_output", ["PHEPG"]), 78 | 47: ("_parse_elem_output", ["SEPE"]), 79 | 48: ("_parse_elem_output", ["TSHR"]), 80 | 49: ("_parse_elem_output", ["PHEFL"]), 81 | 50: ("_parse_elem_output", ["EPG"]), 82 | 51: ("_parse_elem_output", ["EFLX"]), 83 | 52: ("_parse_elem_output", ["XC"]), 84 | 53: ("_parse_elem_output", ["UC"]), 85 | 54: ("_parse_elem_output", ["VC"]), 86 | 55: ("_parse_elem_output", ["HC"]), 87 | 56: ("_parse_elem_output", ["HO"]), 88 | 57: ("_parse_elem_output", ["RI"]), 89 | 58: ("_parse_elem_output", ["MASS"]), 90 | 59: ("_parse_elem_output", ["VOL"]), 91 | 60: ("_parse_elem_output", ["CHRGS"]), 92 | 61: ("_parse_elem_output", ["STATUS"]), 93 | 62: ("_parse_elem_output", ["PHS"]), 94 | 63: ("_parse_elem_output", ["RS"]), 95 | 65: ("_parse_elem_output", ["PHE"]), 96 | 66: ("_parse_elem_output", ["RE"]), 97 | 73: ("_parse_elem_output", ["PEEQ"]), 98 | 74: ("_parse_elem_output", ["PRESS"]), 99 | 75: ("_parse_elem_output", ["MISES"]), 100 | 76: ("_parse_elem_output", ["VOLC"]), 101 | 77: ("_parse_elem_output", ["SVOL"]), 102 | 78: ("_parse_elem_output", ["EVOL"]), 103 | 79: ("_parse_elem_output", ["RATIO"]), 104 | 80: ("_parse_elem_output", ["AMPCU"]), 105 | 83: ("_parse_elem_output", ["SSAVG"]), 106 | 85: ("_parse_local_csys", []), 107 | 86: ("_parse_elem_output", ["ALPHA"]), 108 | 87: ("_parse_elem_output", ["UVARM"]), 109 | 88: ("_parse_elem_output", ["THE"]), 110 | 89: ("_parse_elem_output", ["LE"]), 111 | 90: ("_parse_elem_output", ["NE"]), 112 | 91: ("_parse_elem_output", ["ER"]), 113 | 94: ("_parse_elem_output", ["PHMFL"]), 114 | 95: ("_parse_elem_output", ["PHMFT"]), 115 | 96: ("_parse_elem_output", ["MFLT"]), 116 | 97: ("_parse_elem_output", ["FLVEL"]), 117 | 101: ("_parse_nodal_output", ["U"]), 118 | 102: ("_parse_nodal_output", ["V"]), 119 | 103: ("_parse_nodal_output", ["A"]), 120 | 104: ("_parse_nodal_output", ["RF"]), 121 | 105: ("_parse_nodal_output", ["EPOT"]), 122 | 106: ("_parse_nodal_output", ["CF"]), 123 | 107: ("_parse_nodal_output", ["COORD"]), 124 | 108: ("_parse_nodal_output", ["POR"]), 125 | 109: ("_parse_nodal_output", ["RVF"]), 126 | 110: ("_parse_nodal_output", ["RVT"]), 127 | 111: ("_parse_nodal_output", ["PU"]), 128 | 112: ("_parse_nodal_output", ["PTU"]), 129 | 113: ("_parse_nodal_output", ["TU"]), 130 | 114: ("_parse_nodal_output", ["TV"]), 131 | 115: ("_parse_nodal_output", ["TA"]), 132 | 116: ("_parse_nodal_output", ["PPOR"]), 133 | 117: ("_parse_nodal_output", ["PHPOT"]), 134 | 118: ("_parse_nodal_output", ["PHCHG"]), 135 | 119: ("_parse_nodal_output", ["RCHG"]), 136 | 120: ("_parse_nodal_output", ["CECHG"]), 137 | 123: ("_parse_nodal_output", ["RU"]), 138 | 124: ("_parse_nodal_output", ["RTU"]), 139 | 127: ("_parse_nodal_output", ["RV"]), 140 | 128: ("_parse_nodal_output", ["RTV"]), 141 | 131: ("_parse_nodal_output", ["RA"]), 142 | 131: ("_parse_nodal_output", ["RA"]), 143 | 132: ("_parse_nodal_output", ["RTA"]), 144 | 134: ("_parse_nodal_output", ["RRF"]), 145 | 135: ("_parse_nodal_output", ["PRF"]), 146 | 136: ("_parse_nodal_output", ["PCAV"]), 147 | 137: ("_parse_nodal_output", ["CVOL"]), 148 | 138: ("_parse_nodal_output", ["RECUR"]), 149 | 139: ("_parse_nodal_output", ["CECUR"]), 150 | 145: ("_parse_nodal_output", ["VF"]), 151 | 146: ("_parse_nodal_output", ["TF"]), 152 | 151: ("_parse_nodal_output", ["PABS"]), 153 | 201: ("_parse_nodal_output", ["NT"]), 154 | 204: ("_parse_nodal_output", ["RFL"]), 155 | 206: ("_parse_nodal_output", ["CFL"]), 156 | 214: ("_parse_nodal_output", ["RFLE"]), 157 | 221: ("_parse_nodal_output", ["NNC"]), 158 | 237: ("_parse_nodal_output", ["MOT"]), 159 | 264: ("_parse_nodal_output", ["VOLC"]), 160 | 301: ("_parse_nodal_output", ["GU"]), 161 | 302: ("_parse_nodal_output", ["GV"]), 162 | 303: ("_parse_nodal_output", ["GA"]), 163 | 304: ("_parse_nodal_output", ["BM"]), 164 | 305: ("_parse_nodal_output", ["GPU"]), 165 | 306: ("_parse_nodal_output", ["GPV"]), 166 | 307: ("_parse_nodal_output", ["GPA"]), 167 | 308: ("_parse_nodal_output", ["SNE"]), 168 | 309: ("_parse_nodal_output", ["KE"]), 169 | 310: ("_parse_nodal_output", ["T"]), 170 | 320: ("_parse_nodal_output", ["CFF"]), 171 | 401: ("_parse_elem_output", ["SP"]), 172 | 402: ("_parse_elem_output", ["ALPHAP"]), 173 | 403: ("_parse_elem_output", ["EP"]), 174 | 404: ("_parse_elem_output", ["NEP"]), 175 | 405: ("_parse_elem_output", ["LEP"]), 176 | 406: ("_parse_elem_output", ["ERP"]), 177 | 407: ("_parse_elem_output", ["DGP"]), 178 | 408: ("_parse_elem_output", ["EEP"]), 179 | 409: ("_parse_elem_output", ["IEP"]), 180 | 410: ("_parse_elem_output", ["THEP"]), 181 | 411: ("_parse_elem_output", ["PEP"]), 182 | 412: ("_parse_elem_output", ["CEP"]), 183 | 413: ("_parse_elem_output", ["VVF"]), 184 | 414: ("_parse_elem_output", ["VVFG"]), 185 | 415: ("_parse_elem_output", ["VVFN"]), 186 | 416: ("_parse_elem_output", ["RD"]), 187 | 421: ("_parse_elem_output", ["CKE"]), 188 | 422: ("_parse_elem_output", ["CKLE"]), 189 | 423: ("_parse_elem_output", ["CKLS"]), 190 | 424: ("_parse_elem_output", ["CKSTAT"]), 191 | 425: ("_parse_elem_output", ["ECD"]), 192 | 426: ("_parse_elem_output", ["ECURS"]), 193 | 427: ("_parse_elem_output", ["NCURS"]), 194 | 441: ("_parse_elem_output", ["CKEMAG"]), 195 | 442: ("_parse_elem_output", ["RBFOR"]), 196 | 443: ("_parse_elem_output", ["RBANG"]), 197 | 444: ("_parse_elem_output", ["RBROT"]), 198 | 445: ("_parse_elem_output", ["MFR"]), 199 | 446: ("_parse_elem_output", ["ISOL"]), 200 | 447: ("_parse_elem_output", ["ESOL"]), 201 | 448: ("_parse_elem_output", ["SOL"]), 202 | 449: ("_parse_elem_output", ["ESF1"]), 203 | 462: ("_parse_elem_output", ["SEE"]), 204 | 463: ("_parse_elem_output", ["SEP"]), 205 | 464: ("_parse_elem_output", ["SALPHA"]), 206 | 473: ("_parse_elem_output", ["PEEQT"]), 207 | 475: ("_parse_elem_output", ["CS11"]), 208 | 476: ("_parse_elem_output", ["EMSF"]), 209 | 477: ("_parse_elem_output", ["EDT"]), 210 | 495: ("_parse_elem_output", ["CTF"]), 211 | 496: ("_parse_elem_output", ["CEF"]), 212 | 497: ("_parse_elem_output", ["CVF"]), 213 | 498: ("_parse_elem_output", ["CSF"]), 214 | 499: ("_parse_elem_output", ["CSLST"]), 215 | 500: ("_parse_elem_output", ["CRF"]), 216 | 501: ("_parse_elem_output", ["CCF"]), 217 | 502: ("_parse_elem_output", ["CP"]), 218 | 503: ("_parse_elem_output", ["CU"]), 219 | 504: ("_parse_elem_output", ["CCU"]), 220 | 505: ("_parse_elem_output", ["CV"]), 221 | 506: ("_parse_elem_output", ["CA"]), 222 | 507: ("_parse_elem_output", ["CFAILST"]), 223 | 508: ("_parse_elem_output", ["PHCTF"]), 224 | 509: ("_parse_elem_output", ["PHCEF"]), 225 | 510: ("_parse_elem_output", ["PHCVF"]), 226 | 511: ("_parse_elem_output", ["PHCRF"]), 227 | 512: ("_parse_elem_output", ["PHCU"]), 228 | 513: ("_parse_elem_output", ["PHCCU"]), 229 | 514: ("_parse_elem_output", ["RCTF"]), 230 | 515: ("_parse_elem_output", ["RCEF"]), 231 | 516: ("_parse_elem_output", ["RCVF"]), 232 | 517: ("_parse_elem_output", ["RCRF"]), 233 | 518: ("_parse_elem_output", ["RCU"]), 234 | 519: ("_parse_elem_output", ["RCCU"]), 235 | 520: ("_parse_elem_output", ["PHCSF"]), 236 | 521: ("_parse_elem_output", ["RCSF"]), 237 | 522: ("_parse_elem_output", ["PHCV"]), 238 | 523: ("_parse_elem_output", ["PHCA"]), 239 | 524: ("_parse_elem_output", ["VS"]), 240 | 525: ("_parse_elem_output", ["PS"]), 241 | 526: ("_parse_elem_output", ["VE"]), 242 | 542: ("_parse_elem_output", ["CNF"]), 243 | 543: ("_parse_elem_output", ["PHCNF"]), 244 | 544: ("_parse_elem_output", ["RCNF"]), 245 | 546: ("_parse_elem_output", ["CIVC"]), 246 | 547: ("_parse_elem_output", ["PHCIVSL"]), 247 | 548: ("_parse_elem_output", ["CASU"]), 248 | 556: ("_parse_elem_output", ["CUE"]), 249 | 557: ("_parse_elem_output", ["CUP"]), 250 | 558: ("_parse_elem_output", ["CUPEQ"]), 251 | 559: ("_parse_elem_output", ["CDMG"]), 252 | 560: ("_parse_elem_output", ["CDIF"]), 253 | 561: ("_parse_elem_output", ["CDIM"]), 254 | 562: ("_parse_elem_output", ["CDIP"]), 255 | 563: ("_parse_elem_output", ["CALPHAF"]), 256 | 1501: ("_parse_surface", [False]), 257 | 1502: ("_parse_surface", [True]), 258 | 1503: ("_parse_contact_output_request", []), 259 | 1504: ("_parse_curr_contact_node", []), 260 | 1511: ("_parse_surface_output", ["CSTRESS"]), 261 | 1512: ("_parse_surface_output", ["CDSTRESS"]), 262 | 1521: ("_parse_surface_output", ["CDISP"]), 263 | 1522: ("_parse_surface_output", ["CFN"]), 264 | 1523: ("_parse_surface_output", ["CFS"]), 265 | 1524: ("_parse_surface_output", ["CAREA"]), 266 | 1526: ("_parse_surface_output", ["CMN"]), 267 | 1527: ("_parse_surface_output", ["CMS"]), 268 | 1528: ("_parse_surface_output", ["HFL"]), 269 | 1529: ("_parse_surface_output", ["HFLA"]), 270 | 1530: ("_parse_surface_output", ["HFL"]), 271 | 1531: ("_parse_surface_output", ["HTLA"]), 272 | 1532: ("_parse_surface_output", ["SFDR"]), 273 | 1533: ("_parse_surface_output", ["SFDRA"]), 274 | 1534: ("_parse_surface_output", ["SFDRT"]), 275 | 1535: ("_parse_surface_output", ["SFDRTA"]), 276 | 1536: ("_parse_surface_output", ["WEIGHT"]), 277 | 1537: ("_parse_surface_output", ["SJD"]), 278 | 1538: ("_parse_surface_output", ["SJDA"]), 279 | 1539: ("_parse_surface_output", ["SJDT"]), 280 | 1540: ("_parse_surface_output", ["SJDTA"]), 281 | 1541: ("_parse_surface_output", ["ECD"]), 282 | 1542: ("_parse_surface_output", ["ECDA"]), 283 | 1543: ("_parse_surface_output", ["ECDT"]), 284 | 1544: ("_parse_surface_output", ["ECDTA"]), 285 | 1545: ("_parse_surface_output", ["PFL"]), 286 | 1546: ("_parse_surface_output", ["PFLA"]), 287 | 1547: ("_parse_surface_output", ["PTL"]), 288 | 1548: ("_parse_surface_output", ["PTLA"]), 289 | 1549: ("_parse_surface_output", ["TPFL"]), 290 | 1550: ("_parse_surface_output", ["TPTL"]), 291 | 1570: ("_parse_surface_output", ["DBT"]), 292 | 1571: ("_parse_surface_output", ["DBSF"]), 293 | 1572: ("_parse_surface_output", ["DBS"]), 294 | 1573: ("_parse_surface_output", ["XN"]), 295 | 1574: ("_parse_surface_output", ["XS"]), 296 | 1575: ("_parse_surface_output", ["CFT"]), 297 | 1576: ("_parse_surface_output", ["CMT"]), 298 | 1577: ("_parse_surface_output", ["XT"]), 299 | 1578: ("_parse_surface_output", ["CTRQ"]), 300 | 1592: ("_parse_surface_output", ["CPPRESSTRQ"]), 301 | 1900: ("_parse_element", []), 302 | 1901: ("_parse_node", []), 303 | 1902: ("_parse_active_dof", []), 304 | 1911: ("_parse_output_request", []), 305 | 1921: ("_parse_abaqus_release", []), 306 | 1922: ("_parse_heading", []), 307 | 1931: ("_parse_set", [False, "node"]), 308 | 1932: ("_parse_set", [True, "node"]), 309 | 1933: ("_parse_set", [False, "element"]), 310 | 1934: ("_parse_set", [True, "element"]), 311 | 1940: ("_parse_label_cross_ref", []), 312 | 2000: ("_parse_step", ["start"]), 313 | 2001: ("_parse_step", ["end"]), 314 | } 315 | 316 | CONTACT_OUT = { 317 | "CSTRESS": ["CPRESS", "CSHEAR1", "CSHEAR2"], 318 | } 319 | 320 | def __init__(self, records, progress): 321 | self._records = records 322 | self.model = Model() 323 | 324 | self._curr_elem_out: int = None 325 | self._curr_n_int_points: int = None 326 | self._curr_step: int = None 327 | self._curr_inc: int = None 328 | self._curr_loc_id: int = None 329 | self._flag_output: int = None 330 | self._curr_output_node: int = None 331 | self._output_request_set: str = None 332 | self._output_elem_type: str = None 333 | self._dof_map: dict = dict() 334 | self._model_dimension: int = None 335 | self._node_records: list = list() 336 | 337 | self._curr_set: list = [] 338 | self._tmp_sets: dict = {"element": dict(), "node": dict()} 339 | self._label_cross_ref: dict = dict() 340 | self._curr_surface: int = None 341 | self._tmp_surf: dict = dict() 342 | self._tmp_faces: dict = dict() 343 | self._node_elems: dict = dict() 344 | 345 | self._parse_records(progress) 346 | 347 | def _parse_records(self, progress): 348 | """Parse the imported records.""" 349 | records = self._records 350 | 351 | pattern = re.compile( 352 | r"(?:I(?: \d(\d+))|" # ints with I prefix 353 | + r"[ED]((?: |-)\d+\.\d+(?:E|D)(?:\+|-)\d+)|" # floats with E/D prefix 354 | + r"A(.{8}))" # strings with A prefix 355 | ) 356 | 357 | # Parse each record 358 | for r_i in tqdm(records, disable=(not progress), leave=False, unit="record", 359 | dynamic_ncols=True): 360 | m_rec = pattern.findall(r_i) 361 | 362 | # Get each variable 363 | vars_i = list(map(self._convert_record, m_rec)) 364 | 365 | # Process record 366 | key = vars_i[1] 367 | # Lookup the key in dictionary and execute the respective functions 368 | if key in self.PARSE_MAP: 369 | args = self.PARSE_MAP[key][1] 370 | getattr(self, self.PARSE_MAP[key][0])(vars_i, *args) 371 | else: 372 | print(f"Key {key} not defined!") 373 | 374 | # Execute post-read actions on the model 375 | self._post_parse_all_surfaces() 376 | self._reference_elems_in_nodes() 377 | self.model.post_import_actions() 378 | 379 | def _convert_record(self, record): 380 | """Convert one record to a list of numbers and strings.""" 381 | # For each variable three matches are made (why?), so we need to 382 | # take the one with the data (the only one which is not am empty 383 | # string) 384 | if record[0] != "": 385 | return int(record[0]) 386 | elif record[1] != "": 387 | return float(record[1].replace("D", "E")) 388 | else: 389 | return record[2] 390 | 391 | def _parse_element(self, record): 392 | """Parse the data of an element 393 | 394 | Parameters 395 | ---------- 396 | record : list 397 | 398 | """ 399 | # Element type 400 | e_type = record[3].strip() 401 | e_number = record[2] 402 | nodes = record[4:] 403 | 404 | # Add a reference to the node poinitng at the element 405 | for n in nodes: 406 | if n in self._node_elems.keys(): 407 | self._node_elems[n].append(e_number) 408 | else: 409 | self._node_elems[n] = [e_number] 410 | if e_type in ELEMENTS.keys(): 411 | ElementClass = ELEMENTS[e_type] 412 | else: 413 | _log.warning(f"Element type {e_type} not supported yet. Skipping.") 414 | return 415 | 416 | element = ElementClass(*nodes, num=e_number, model=self.model, code=e_type) 417 | element.n_integ_points = N_INT_PNTS[e_type] 418 | self.model.add_element(element) 419 | 420 | def _parse_node(self, record): 421 | """Parse the data of a node 422 | 423 | Parameters 424 | ---------- 425 | record : list 426 | 427 | """ 428 | # Wait until the 'Active degree of freedom' key has been processed 429 | if self._model_dimension is None: 430 | self._node_records.append(record) 431 | else: 432 | n_number = record[2] 433 | dofs = record[3:] 434 | dof_map = self._dof_map 435 | 436 | if self._model_dimension == 2: 437 | node = Node2D(n_number, dof_map, self.model, *dofs) 438 | else: 439 | node = Node3D(n_number, dof_map, self.model, *dofs) 440 | 441 | self.model.add_node(node) 442 | 443 | def _parse_all_nodes(self): 444 | """Parse all nodes. 445 | 446 | This has to be executed after the active degree of freedom 447 | are specified. 448 | 449 | Parameters 450 | ---------- 451 | records : list 452 | A list of all the records with nodes 453 | 454 | Returns 455 | ------- 456 | TODO 457 | 458 | """ 459 | records = self._node_records 460 | 461 | for record in records: 462 | self._parse_node(record) 463 | 464 | self._node_records = list() 465 | 466 | def _parse_elem_output(self, record, var): 467 | """Parse output data for elements. 468 | 469 | Parameters 470 | ---------- 471 | record : list 472 | var : str 473 | Name of the variable 474 | 475 | Returns 476 | ------- 477 | TODO 478 | 479 | """ 480 | step = self._curr_step 481 | inc = self._curr_inc 482 | 483 | # This flags the type of output: element (0), nodal (1), modal 484 | # (2), or element set energy (3) 485 | flag_out = self._flag_output 486 | 487 | if flag_out == 0: 488 | n_elem = self._curr_elem_out 489 | # Get number of integration points 490 | int_point = self._curr_n_int_point 491 | 492 | # Append all the records 493 | for ix, data in enumerate(record[2:], start=1): 494 | self.model.add_elem_output(n_elem, f"{var}{ix}", data, step, inc, int_point) 495 | 496 | elif flag_out == 1: 497 | n_node = self._curr_elem_out 498 | 499 | for ix, data in enumerate(record[2:], start=1): 500 | self.model.add_nodal_output(n_node, f"{var}{ix}", data, step, inc) 501 | 502 | elif flag_out == 2: 503 | # TODO: implement modal output 504 | pass 505 | 506 | # flag_out == 3: 507 | else: 508 | # TODO: implement set energy output 509 | pass 510 | 511 | def _parse_elem_header(self, record): 512 | """Parse the element record 513 | 514 | Parameters 515 | ---------- 516 | record : TODO 517 | 518 | Returns 519 | ------- 520 | TODO 521 | 522 | """ 523 | num = record[2] 524 | n_int_point = record[3] 525 | n_sec_point = record[4] 526 | # loc_id: 527 | # - 0 if the subsequent records contain data at an integration point; 528 | # - 1 if the subsequent records contain values at the centroid of the element; 529 | # - 2 if the subsequent records contain data at the nodes of the element; 530 | # - 3 if the subsequent records contain data associated with rebar within an element; 531 | # - 4 if the subsequent records contain nodal averaged values; 532 | # - 5 if the subsequent records contain values associated with the whole element 533 | loc_id = record[5] 534 | name_rebar = record[6] 535 | n_direct_stresses = record[7] 536 | n_shear_stresses = record[8] 537 | n_diretions = record[9] 538 | n_sec_force_comp = record[10] 539 | 540 | # Append the element/node number to the list of elements/nodes which 541 | # data is going to be read next 542 | self._curr_elem_out = num 543 | self._curr_n_int_point = n_int_point 544 | self._curr_loc_id = loc_id 545 | self._curr_int_point_data = dict() 546 | 547 | def _parse_nodal_output(self, record, var): 548 | """Parse the nodal record 549 | 550 | Parameters 551 | ---------- 552 | record : TODO 553 | 554 | Returns 555 | ------- 556 | TODO 557 | 558 | """ 559 | step = self._curr_step 560 | inc = self._curr_inc 561 | 562 | if len(record) > 2: 563 | for ix, r_i in enumerate(record[3:], start=1): 564 | self.model.add_nodal_output(node=record[2], var=f"{var}{ix}", data=r_i, 565 | step=step, inc=inc) 566 | else: 567 | self.model.add_nodal_output(node=record[0], var=var, data=record[1], step=step, 568 | inc=inc) 569 | 570 | return 1 571 | 572 | def _parse_surface_output(self, record, var): 573 | """Parse results from surfaces. 574 | 575 | Parameters 576 | ---------- 577 | record : TODO 578 | var : str 579 | Name of the variable to be processed, e.g.: "CSTRESS" 580 | 581 | Returns 582 | ------- 583 | TODO 584 | 585 | """ 586 | step = self._curr_step 587 | inc = self._curr_inc 588 | node = self._curr_output_node 589 | 590 | for ix, comp_i in enumerate(record[2:]): 591 | self.model.add_nodal_output(node=node, var=self.CONTACT_OUT[var][ix], 592 | data=comp_i, step=step, inc=inc) 593 | 594 | def _parse_contact_output_request(self, record): 595 | """Parse surfaces and nodes associated to contact pair. 596 | 597 | Parameters 598 | ---------- 599 | record : TODO 600 | 601 | """ 602 | id_slave = int(record[3].strip()) 603 | id_master = int(record[4].strip()) 604 | name_slave = self._label_cross_ref[id_slave] 605 | name_master = self._label_cross_ref[id_master] 606 | self.model.add_contact_pair(master=name_master, slave=name_slave) 607 | 608 | def _parse_curr_contact_node(self, record): 609 | """Parse the current node associated to the surface output. 610 | 611 | Parameters 612 | ---------- 613 | record : TODO 614 | 615 | """ 616 | self._curr_output_node = record[2] 617 | self._no_of_components = record[3] 618 | 619 | def _parse_output_request(self, record): 620 | """Parse the output request 621 | 622 | Parameters 623 | ---------- 624 | record : TODO 625 | 626 | """ 627 | self._flag_output = record[2] 628 | self._output_request_set = record[3] 629 | if self._flag_output == 0: 630 | self._output_elem_type = record[4] 631 | 632 | def _parse_step(self, record, flag): 633 | """Parse the current step 634 | 635 | Parameters 636 | ---------- 637 | record : TODO 638 | 639 | Returns 640 | ------- 641 | TODO 642 | 643 | """ 644 | if flag == "start": 645 | n_step = record[7] 646 | n_inc = record[8] 647 | 648 | data = { 649 | "total time": record[2], 650 | "step time": record[3], 651 | "max creep": record[4], 652 | "solution amplitude": record[5], 653 | "procedure type": record[6], 654 | "step number": record[7], 655 | "increment number": record[8], 656 | "linear perturbation": record[9], 657 | "load proportionality": record[10], 658 | "frequency": record[11], 659 | "time increment": record[12], 660 | "subheading": "".join(record[13:]), 661 | } 662 | 663 | self.model.add_step(n_step, data) 664 | 665 | self._curr_step = n_step 666 | self._curr_inc = n_inc 667 | else: 668 | self._curr_step = None 669 | self._curr_inc = None 670 | 671 | def _parse_active_dof(self, record): 672 | """Parse the active degrees of freedom. 673 | 674 | Parameters 675 | ---------- 676 | record : TODO 677 | 678 | Returns 679 | ------- 680 | TODO 681 | 682 | """ 683 | active_dof = np.asarray(record[2:], dtype=int) 684 | # Determine the dimension of the model 685 | dimension = np.sum(np.not_equal(active_dof[:3], np.zeros(3)), dtype=int) 686 | self._model_dimension = dimension 687 | self.model._dimension = dimension 688 | 689 | # (k + 1): because the dof's start at 1 690 | # (val - 1): because they will be referenced to a list, which is 0-indexed 691 | # self._dof_map = {(k + 1): (val - 1) if val != 0 else 0 692 | # for k, val in enumerate(active_dof)} 693 | self._dof_map = active_dof 694 | 695 | # Process all nodes 696 | self._parse_all_nodes() 697 | 698 | def _parse_set(self, record, add, s_type): 699 | """Parse the element sets 700 | 701 | Parameters 702 | ---------- 703 | record : TODO 704 | add : bool 705 | Flags whether records are added to an existing set or a new set has to be 706 | created. 707 | s_type : str 708 | Type of set ("element", "node") 709 | 710 | """ 711 | if add: 712 | elements = record[2:] 713 | ref = self._curr_set 714 | self._curr_set.extend(elements) 715 | else: 716 | elements = record[3:] 717 | # If the name of the set is longer than 8 chars, then an integer 718 | # identifier is given 719 | label = record[2].strip() 720 | 721 | try: 722 | int(label) 723 | integer_label = True 724 | except: 725 | integer_label = False 726 | 727 | # If we have an integer identifier, then we add the elements to 728 | # a temporary dictionary, which is cross-referenced with the real 729 | # label later (processing of record 1940). 730 | if integer_label: 731 | ref = int(label) 732 | self._tmp_sets[s_type][ref] = elements 733 | self._curr_set = self._tmp_sets[s_type][ref] 734 | # Otherwise we create a new set and use it directly. 735 | else: 736 | label = record[2].strip() 737 | curr_set = self.model.add_set(label, elements, s_type) 738 | self._curr_set = curr_set 739 | 740 | def _parse_surface(self, record, add_face): 741 | """Parse the surface records. 742 | 743 | Parameters 744 | ---------- 745 | record : list 746 | Record entry from the *.fil file. 747 | add_face : bool 748 | Flag to determine whether a face has to be added to an existing surface 749 | (True), or whether a new surfaces has to be created (False) 750 | 751 | """ 752 | if add_face: 753 | # Add faces to existing surface 754 | label = self._curr_surface 755 | 756 | face_info = { 757 | "element": record[2], 758 | "face": record[3], 759 | "nodes": record[5:], 760 | } 761 | self._tmp_faces[label].append(face_info) 762 | 763 | else: 764 | # Create new surface container 765 | s_type = record[4] 766 | name = int(record[2].strip()) 767 | dim = record[3] 768 | n_faces = record[5] 769 | 770 | # Set temporary variable 771 | self._curr_surface = name 772 | # Start corresponding container for the surface 773 | self._tmp_faces[name] = list() 774 | 775 | if s_type == 1: 776 | # Deformable surface 777 | n_slaves = record[6] 778 | if n_slaves > 0: 779 | master_names = record[7:] 780 | else: 781 | master_names = [] 782 | 783 | self._tmp_surf[name] = { 784 | "dimension": dim, 785 | "type": "deformable", 786 | "master names": master_names, 787 | } 788 | 789 | elif s_type == 2: 790 | # Rigid surface 791 | ref_label = record[6] 792 | self._tmp_surf[name] = { 793 | "dimension": dim, 794 | "type": "rigid", 795 | "reference point": ref_label, 796 | } 797 | 798 | def _parse_local_csys(self, record): 799 | """Parse the local coordinate systems if available. 800 | 801 | Parameters 802 | ---------- 803 | record : list 804 | Records parsed from the *.fil file 805 | 806 | """ 807 | # Get element being currently processed 808 | curr_elem = self._curr_elem_out 809 | 810 | # The local coordinate system is saved for each increment, so we need 811 | # to get the current step and increments. 812 | curr_step = self.model._curr_out_step 813 | curr_inc = self.model._curr_incr 814 | 815 | if self._model_dimension == 3: 816 | dir_1 = np.asarray(record[2:5], dtype=float) 817 | dir_2 = np.asarray(record[5:], dtype=float) 818 | # Only the first two directions are given, but we can compute the 819 | # third direction with a cross-prouct. 820 | dir_3 = np.cross(dir_1, dir_2) 821 | # Stack all directions into one array 822 | csys = np.vstack((dir_1, dir_2, dir_3)) 823 | self.model.add_local_csys(curr_elem, csys, step=curr_step, inc=curr_inc) 824 | 825 | elif self._model_dimension == 2: 826 | dir_1 = np.asarray(record[2:4], dtype=float) 827 | dir_2 = np.asarray(record[4:], dtype=float) 828 | # Stack all directions into one array 829 | csys = np.vstack((dir_1, dir_2)) 830 | self.model.add_local_csys(curr_elem, csys, step=curr_step, inc=curr_inc) 831 | 832 | def _post_parse_all_surfaces(self): 833 | """Process all the surfaces after reading all records.""" 834 | surfaces = self._tmp_surf 835 | faces = self._tmp_faces 836 | model = self.model 837 | 838 | for ix, surf in surfaces.items(): 839 | if surf["type"] == "rigid": 840 | # Get name 841 | name = self._label_cross_ref[ix] 842 | dim = surf["dimension"] 843 | ref = surf["reference point"] 844 | model.add_rigid_surface(name, dim, ref) 845 | 846 | for face_i in faces[ix]: 847 | model.add_face_to_surface(name, face_i) 848 | 849 | elif surf["type"] == "deformable": 850 | # Get name 851 | name = self._label_cross_ref[ix] 852 | dim = surf["dimension"] 853 | master = surf["master names"] 854 | self.model.add_deformable_surface(name, dim, master) 855 | 856 | for face_i in faces[ix]: 857 | model.add_face_to_surface(name, face_i) 858 | 859 | def _parse_label_cross_ref(self, record): 860 | """Parse label cross-references 861 | 862 | Parameters 863 | ---------- 864 | record : list 865 | Records parsed from the *.fil file 866 | 867 | """ 868 | # Get reference number of the set 869 | ref = record[2] 870 | # Get name of the set 871 | label = "".join(record[3:]).strip() 872 | 873 | self._label_cross_ref[ref] = label 874 | 875 | tmp_sets = self._tmp_sets 876 | 877 | if ref in tmp_sets["element"]: 878 | elements = tmp_sets["element"][ref] 879 | self.model.add_set(label, elements, "element") 880 | elif ref in tmp_sets["node"]: 881 | elements = tmp_sets["node"][ref] 882 | self.model.add_set(label, elements, "node") 883 | 884 | def _parse_abaqus_release(self, record): 885 | release = record[2].strip() 886 | date = (record[3] + record[4]).strip() 887 | time = record[5].strip() 888 | elen = record[8] 889 | 890 | self.model.add_release_info(release, date, time) 891 | self.model.size = (record[6], record[7]) 892 | self.model.elen = elen 893 | 894 | def _parse_heading(self, record): 895 | heading = "".join(record[2:]).strip() 896 | self.model.heading = heading 897 | 898 | def _parse_not_implemented(self, record, r_type): 899 | """Helper function to deal with the not yet implemented parsers. 900 | 901 | Parameters 902 | ---------- 903 | record : TODO 904 | r_type : str 905 | 906 | """ 907 | #tqdm.write(f"Record key {record[1]} ({r_type}) not yet implemented!") 908 | print(f"Record key {record[1]} ({r_type}) not yet implemented!") 909 | 910 | def _reference_elems_in_nodes(self): 911 | """Add a list to each node with the elements using the node.""" 912 | model = self.model 913 | 914 | for ni, elems in self._node_elems.items(): 915 | model.nodes[ni].in_elements = elems 916 | --------------------------------------------------------------------------------