Coverage for src/beamme/core/element_beam.py: 82%

33 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-07-28 15:20 +0000

1# The MIT License (MIT) 

2# 

3# Copyright (c) 2018-2026 BeamMe Authors 

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 

13# all 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 

21# THE SOFTWARE. 

22"""This file defines the base beam element.""" 

23 

24from typing import Any as _Any 

25 

26import numpy as _np 

27import pyvista as _pv 

28 

29from beamme.core.conf import bme as _bme 

30from beamme.core.element import Element as _Element 

31 

32 

33class Beam(_Element): 

34 """A base class for a beam element.""" 

35 

36 # Cell type for representing this element in vtk. 

37 vtk_cell_type = _pv.CellType.POLY_LINE 

38 

39 # Type of this element. 

40 element_type = _bme.element_type.beam 

41 

42 # An array that defines the parameter positions of the element nodes, 

43 # in ascending order. 

44 nodes_create: _Any = [] 

45 

46 def __init__(self, material=None, nodes=None): 

47 super().__init__(nodes=nodes, material=material) 

48 

49 @classmethod 

50 def get_coupling_dict(cls, coupling_dof_type): 

51 """Return the dict to couple this beam to another beam.""" 

52 match coupling_dof_type: 

53 case _bme.coupling_dof.joint: 

54 if cls.coupling_joint_dict is None: 

55 raise ValueError(f"Joint coupling is not implemented for {cls}") 

56 return cls.coupling_joint_dict 

57 case _bme.coupling_dof.fix: 

58 if cls.coupling_fix_dict is None: 

59 raise ValueError("Fix coupling is not implemented for {cls}") 

60 return cls.coupling_fix_dict 

61 case _: 

62 raise ValueError( 

63 f'Coupling_dof_type "{coupling_dof_type}" is not implemented!' 

64 ) 

65 

66 def flip(self): 

67 """Reverse the nodes of this element. 

68 

69 This is usually used when reflected. 

70 """ 

71 self.nodes = [self.nodes[-1 - i] for i in range(len(self.nodes))] 

72 

73 

74def generate_beam_class(n_nodes: int): 

75 """Return a class representing a general beam with n_nodes in BeamMe. 

76 

77 Args: 

78 n_nodes: Number of equally spaced nodes along the beam centerline. 

79 

80 Returns: 

81 A beam object that has n_nodes along the centerline. 

82 """ 

83 # Define the class variable responsible for creating the nodes. 

84 nodes_create = _np.linspace(-1, 1, num=n_nodes) 

85 

86 # Create the beam class which inherits from the base beam class. 

87 return type(f"Beam{n_nodes}", (Beam,), {"nodes_create": nodes_create, "data": None}) 

88 

89 

90Beam2 = generate_beam_class(2) 

91Beam3 = generate_beam_class(3) 

92Beam4 = generate_beam_class(4) 

93Beam5 = generate_beam_class(5)