pyroll-core 2.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. pyroll/core/__init__.py +38 -0
  2. pyroll/core/config.py +155 -0
  3. pyroll/core/disk_elements/__init__.py +2 -0
  4. pyroll/core/disk_elements/disk_element_unit.py +73 -0
  5. pyroll/core/disk_elements/hookimpls.py +26 -0
  6. pyroll/core/grooves/__init__.py +10 -0
  7. pyroll/core/grooves/base.py +59 -0
  8. pyroll/core/grooves/boxes/__init__.py +3 -0
  9. pyroll/core/grooves/boxes/box.py +57 -0
  10. pyroll/core/grooves/boxes/constricted_box.py +63 -0
  11. pyroll/core/grooves/boxes/upset_box.py +18 -0
  12. pyroll/core/grooves/diamonds/__init__.py +3 -0
  13. pyroll/core/grooves/diamonds/diamond.py +60 -0
  14. pyroll/core/grooves/diamonds/gothic.py +41 -0
  15. pyroll/core/grooves/diamonds/square.py +48 -0
  16. pyroll/core/grooves/flat.py +31 -0
  17. pyroll/core/grooves/generic_elongation.py +258 -0
  18. pyroll/core/grooves/generic_elongation_solvers.py +422 -0
  19. pyroll/core/grooves/hexagonal.py +57 -0
  20. pyroll/core/grooves/ovals/__init__.py +8 -0
  21. pyroll/core/grooves/ovals/circular_oval.py +43 -0
  22. pyroll/core/grooves/ovals/constricted_circular_oval.py +53 -0
  23. pyroll/core/grooves/ovals/constricted_swedish_oval.py +61 -0
  24. pyroll/core/grooves/ovals/flat_oval.py +56 -0
  25. pyroll/core/grooves/ovals/oval_3radii.py +47 -0
  26. pyroll/core/grooves/ovals/oval_3radii_flanked.py +65 -0
  27. pyroll/core/grooves/ovals/swedish_oval.py +57 -0
  28. pyroll/core/grooves/ovals/upset_oval.py +47 -0
  29. pyroll/core/grooves/rounds/__init__.py +2 -0
  30. pyroll/core/grooves/rounds/false_round.py +65 -0
  31. pyroll/core/grooves/rounds/round.py +44 -0
  32. pyroll/core/grooves/spline.py +92 -0
  33. pyroll/core/hooks.py +420 -0
  34. pyroll/core/log.py +7 -0
  35. pyroll/core/profile/__init__.py +3 -0
  36. pyroll/core/profile/hookimpls.py +58 -0
  37. pyroll/core/profile/profile.py +380 -0
  38. pyroll/core/repr.py +49 -0
  39. pyroll/core/roll/__init__.py +3 -0
  40. pyroll/core/roll/hookimpls.py +65 -0
  41. pyroll/core/roll/roll.py +145 -0
  42. pyroll/core/roll_pass/__init__.py +8 -0
  43. pyroll/core/roll_pass/deformation_unit.py +61 -0
  44. pyroll/core/roll_pass/hookimpls/__init__.py +5 -0
  45. pyroll/core/roll_pass/hookimpls/deformation_unit.py +78 -0
  46. pyroll/core/roll_pass/hookimpls/disk_element.py +16 -0
  47. pyroll/core/roll_pass/hookimpls/profile.py +94 -0
  48. pyroll/core/roll_pass/hookimpls/roll.py +43 -0
  49. pyroll/core/roll_pass/hookimpls/roll_pass.py +107 -0
  50. pyroll/core/roll_pass/roll_pass.py +168 -0
  51. pyroll/core/roll_pass/three_roll_pass.py +84 -0
  52. pyroll/core/rotator/__init__.py +3 -0
  53. pyroll/core/rotator/hookimpls.py +71 -0
  54. pyroll/core/rotator/rotator.py +65 -0
  55. pyroll/core/sequence/__init__.py +3 -0
  56. pyroll/core/sequence/hookimpls.py +18 -0
  57. pyroll/core/sequence/sequence.py +68 -0
  58. pyroll/core/shapes.py +104 -0
  59. pyroll/core/transport/__init__.py +3 -0
  60. pyroll/core/transport/hookimpls.py +17 -0
  61. pyroll/core/transport/transport.py +57 -0
  62. pyroll/core/unit/__init__.py +3 -0
  63. pyroll/core/unit/hookimpls.py +67 -0
  64. pyroll/core/unit/unit.py +271 -0
  65. pyroll_core-2.0.0.dist-info/METADATA +109 -0
  66. pyroll_core-2.0.0.dist-info/RECORD +68 -0
  67. pyroll_core-2.0.0.dist-info/WHEEL +4 -0
  68. pyroll_core-2.0.0.dist-info/licenses/LICENSE +11 -0
@@ -0,0 +1,57 @@
1
+ from typing import Optional
2
+
3
+ import numpy as np
4
+
5
+ from .generic_elongation import GenericElongationGroove
6
+ from .generic_elongation_solvers import solve_box_like
7
+
8
+
9
+ class HexagonalGroove(GenericElongationGroove):
10
+ """Represents a hexagonal-shaped groove."""
11
+
12
+ def __init__(
13
+ self,
14
+ r1: float,
15
+ r2: float,
16
+ depth: float,
17
+ ground_width: Optional[float] = None,
18
+ even_ground_width: Optional[float] = None,
19
+ usable_width: Optional[float] = None,
20
+ flank_angle: Optional[float] = None,
21
+ pad_angle: float = 0,
22
+ **kwargs
23
+ ):
24
+ """
25
+ Exactly two of ``ground_width``, ``even_ground_width``, ``usable_width`` and ``flank_angle`` must be given,
26
+ but not ``ground_width`` and ``even_ground_width`` at the same time.
27
+ Widths are always measured at the intersection of the extrapolated ground, face and flanks.
28
+ All angles are measured in ° (degree).
29
+
30
+ :param r1: radius 1 (face/flank)
31
+ :param r2: radius 2 (flank/ground)
32
+ :param depth: maximum depth
33
+ :param ground_width: width of the groove ground
34
+ :param even_ground_width: width of the even ground line
35
+ :param usable_width: usable width of the groove
36
+ :param flank_angle: inclination angle of the flanks
37
+ :param pad_angle: angle between z-axis and the roll face padding
38
+ :param kwargs: more keyword arguments passed to the GenericElongationGroove constructor
39
+ :raises ValueError: if not exactly two of ground_width, usable_width and flank_angle are given
40
+ """
41
+ if flank_angle is not None:
42
+ flank_angle = np.deg2rad(flank_angle)
43
+
44
+ sol = solve_box_like(
45
+ r2=r2, r4=0, depth=depth, ground_width=ground_width, usable_width=usable_width, flank_angle=flank_angle,
46
+ indent=0, even_ground_width=even_ground_width
47
+ )
48
+
49
+ super().__init__(
50
+ r1=r1, r2=r2, pad_angle=np.deg2rad(pad_angle),
51
+ **sol,
52
+ **kwargs
53
+ )
54
+
55
+ @property
56
+ def classifiers(self):
57
+ return {"hexagonal"} | super().classifiers
@@ -0,0 +1,8 @@
1
+ from .circular_oval import CircularOvalGroove
2
+ from .flat_oval import FlatOvalGroove
3
+ from .swedish_oval import SwedishOvalGroove
4
+ from .constricted_swedish_oval import ConstrictedSwedishOvalGroove
5
+ from .oval_3radii import Oval3RadiiGroove
6
+ from .oval_3radii_flanked import Oval3RadiiFlankedGroove
7
+ from .upset_oval import UpsetOvalGroove
8
+ from .constricted_circular_oval import ConstrictedCircularOvalGroove
@@ -0,0 +1,43 @@
1
+ from typing import Optional
2
+
3
+ import numpy as np
4
+
5
+ from ..generic_elongation import GenericElongationGroove
6
+ from ..generic_elongation_solvers import solve_r124
7
+
8
+
9
+ class CircularOvalGroove(GenericElongationGroove):
10
+ """Represents an oval-shaped groove with one main radius."""
11
+
12
+ def __init__(
13
+ self,
14
+ r1: float,
15
+ r2: Optional[float] = None,
16
+ depth: Optional[float] = None,
17
+ usable_width: Optional[float] = None,
18
+ pad_angle: float = 0,
19
+ **kwargs
20
+ ):
21
+ """
22
+ Give exactly two of ``r2``, ``depth`` or ``usable_width``.
23
+
24
+ :param r1: radius 1 (face/flank)
25
+ :param r2: radius 2 (flank/ground)
26
+ :param depth: maximum depth
27
+ :param usable_width: usable width
28
+ :param pad_angle: angle between z-axis and the roll face padding
29
+ :param kwargs: more keyword arguments passed to the GenericElongationGroove constructor
30
+ """
31
+ pad_angle = np.deg2rad(pad_angle)
32
+
33
+ sol = solve_r124(r1=r1, r2=r2, depth=depth, width=usable_width, pad_angle=pad_angle)
34
+
35
+ super().__init__(
36
+ r2=sol["r2"], depth=sol["depth"], usable_width=sol["width"], flank_angle=sol["alpha"],
37
+ r1=r1, pad_angle=pad_angle,
38
+ **kwargs
39
+ )
40
+
41
+ @property
42
+ def classifiers(self):
43
+ return {"oval", "circular_oval"} | super().classifiers
@@ -0,0 +1,53 @@
1
+ from typing import Optional
2
+
3
+ import numpy as np
4
+
5
+ from ..generic_elongation import GenericElongationGroove
6
+ from ..generic_elongation_solvers import solve_r1234
7
+
8
+
9
+ class ConstrictedCircularOvalGroove(GenericElongationGroove):
10
+ """Represents an oval-shaped groove with one main radius."""
11
+
12
+ def __init__(
13
+ self,
14
+ r1: float,
15
+ r2: float,
16
+ r3: float,
17
+ r4: float,
18
+ depth: float,
19
+ usable_width: float,
20
+ indent: float,
21
+ even_ground_width: float = 0,
22
+ pad_angle: float = 0,
23
+ **kwargs
24
+ ):
25
+ """
26
+ Widths are always measured at the intersection of the extrapolated ground, face and flanks.
27
+
28
+ :param r1: radius 1 (face/flank)
29
+ :param r2: radius 2 (flank/ground)
30
+ :param r3: radius 3 (ground)
31
+ :param r4: radius 4 (indent)
32
+ :param depth: maximum depth
33
+ :param usable_width: usable width of the groove
34
+ :param even_ground_width: width of the even ground line
35
+ :param pad_angle: angle between z-axis and the roll face padding
36
+ :param kwargs: more keyword arguments passed to the GenericElongationGroove constructor
37
+ """
38
+
39
+ pad_angle = np.deg2rad(pad_angle)
40
+
41
+ sol = solve_r1234(r1, r2, r3, r4, depth, usable_width - even_ground_width, indent, pad_angle)
42
+
43
+ super().__init__(
44
+ usable_width=usable_width, depth=depth, indent=indent,
45
+ even_ground_width=even_ground_width,
46
+ r1=r1, r2=r2, r3=r3, r4=r4,
47
+ flank_angle=sol["flank_angle"], alpha3=sol["alpha3"], alpha4=sol["alpha4"], pad_angle=pad_angle,
48
+ **kwargs
49
+ )
50
+
51
+ @property
52
+ def classifiers(self):
53
+ return {"oval", "circular_oval", "constricted"} | super().classifiers
@@ -0,0 +1,61 @@
1
+ from typing import Optional
2
+
3
+ import numpy as np
4
+
5
+ from ..generic_elongation import GenericElongationGroove
6
+ from ..generic_elongation_solvers import solve_box_like
7
+
8
+
9
+ class ConstrictedSwedishOvalGroove(GenericElongationGroove):
10
+ """Represents a hexagonal-shaped groove with an indented ground that is used like an oval groove (swedish oval)."""
11
+
12
+ def __init__(
13
+ self,
14
+ r1: float,
15
+ r2: float,
16
+ r4: float,
17
+ depth: float,
18
+ indent: float,
19
+ ground_width: Optional[float] = None,
20
+ even_ground_width: Optional[float] = None,
21
+ usable_width: Optional[float] = None,
22
+ flank_angle: Optional[float] = None,
23
+ pad_angle: float = 0,
24
+ **kwargs
25
+ ):
26
+ """
27
+ Exactly two of ``ground_width``, ``even_ground_width``, ``usable_width`` and ``flank_angle`` must be given,
28
+ but not ``ground_width`` and ``even_ground_width`` at the same time.
29
+ Widths are always measured at the intersection of the extrapolated ground, face and flanks.
30
+ All angles are measured in ° (degree).
31
+
32
+ :param r1: radius 1 (face/flank)
33
+ :param r2: radius 2 (flank)
34
+ :param r4: radius 4 (indent)
35
+ :param depth: maximum depth
36
+ :param indent: depth of the indent
37
+ :param ground_width: width of the groove ground
38
+ :param even_ground_width: width of the even ground line
39
+ :param usable_width: usable width of the groove
40
+ :param flank_angle: inclination angle of the flanks
41
+ :param pad_angle: angle between z-axis and the roll face padding
42
+ :param kwargs: more keyword arguments passed to the GenericElongationGroove constructor
43
+ :raises ValueError: if not exactly two of ground_width, usable_width and flank_angle are given
44
+ """
45
+ if flank_angle is not None:
46
+ flank_angle = np.deg2rad(flank_angle)
47
+
48
+ sol = solve_box_like(
49
+ r2=r2, r4=r4, depth=depth, ground_width=ground_width, usable_width=usable_width, flank_angle=flank_angle,
50
+ indent=indent, even_ground_width=even_ground_width
51
+ )
52
+
53
+ super().__init__(
54
+ r1=r1, r2=r2, r4=r4, pad_angle=np.deg2rad(pad_angle), indent=indent,
55
+ **sol,
56
+ **kwargs
57
+ )
58
+
59
+ @property
60
+ def classifiers(self):
61
+ return {"oval", "swedish_oval", "constricted_swedish_oval"} | super().classifiers
@@ -0,0 +1,56 @@
1
+ from typing import Optional
2
+
3
+ import numpy as np
4
+
5
+ from ..generic_elongation import GenericElongationGroove
6
+ from ..generic_elongation_solvers import solve_r124
7
+
8
+
9
+ class FlatOvalGroove(GenericElongationGroove):
10
+ """Represent an oval-shaped groove with a flat ground."""
11
+
12
+ def __init__(
13
+ self,
14
+ r1: float,
15
+ r2: float,
16
+ depth: float,
17
+ usable_width: Optional[float] = None,
18
+ even_ground_width: Optional[float] = None,
19
+ pad_angle: float = 0,
20
+ **kwargs
21
+ ):
22
+ """
23
+ Give exactly one of ``usable_width`` and ``even_ground_width``.
24
+
25
+ :param r1: radius 1 (face/flank)
26
+ :param r2: radius 2 (flank/ground)
27
+ :param depth: maximum depth
28
+ :param usable_width: usable width
29
+ :param even_ground_width: width of the straight ground line
30
+ :param pad_angle: angle between z-axis and the roll face padding
31
+ :param kwargs: more keyword arguments passed to the GenericElongationGroove constructor
32
+ """
33
+ pad_angle = np.deg2rad(pad_angle)
34
+
35
+ sol = solve_r124(r1=r1, r2=r2, depth=depth, width=None, pad_angle=pad_angle)
36
+
37
+ if usable_width is None and even_ground_width is not None:
38
+ super().__init__(
39
+ r2=sol["r2"], depth=sol["depth"], usable_width=even_ground_width + sol["width"],
40
+ flank_angle=sol["alpha"], even_ground_width=even_ground_width,
41
+ r1=r1, pad_angle=pad_angle,
42
+ **kwargs
43
+ )
44
+ elif even_ground_width is None and usable_width is not None:
45
+ super().__init__(
46
+ r2=sol["r2"], depth=sol["depth"], usable_width=usable_width, flank_angle=sol["alpha"],
47
+ even_ground_width=usable_width - sol["width"],
48
+ r1=r1, pad_angle=pad_angle,
49
+ **kwargs
50
+ )
51
+ else:
52
+ raise TypeError("Give exactly one of usable_width and even_ground_width.")
53
+
54
+ @property
55
+ def classifiers(self):
56
+ return {"oval", "flat_oval"} | super().classifiers
@@ -0,0 +1,47 @@
1
+ from typing import Optional
2
+ import numpy as np
3
+ from scipy.optimize import minimize, Bounds
4
+ from numpy import sin, cos, tan, pi, array
5
+ from ..generic_elongation import GenericElongationGroove
6
+ from ..generic_elongation_solvers import solve_r123
7
+
8
+
9
+ class Oval3RadiiGroove(GenericElongationGroove):
10
+ """Represents an oval-shaped groove with 3 main radii."""
11
+
12
+ def __init__(
13
+ self,
14
+ r1: float,
15
+ r2: float,
16
+ r3: float,
17
+ depth: float,
18
+ usable_width: float,
19
+ pad_angle: float = 0,
20
+ **kwargs
21
+ ):
22
+ """
23
+ Widths are always measured at the intersection of the extrapolated ground, face and flanks.
24
+
25
+ :param r1: radius 1 (face/flank)
26
+ :param r2: radius 2 (flank/ground)
27
+ :param r3: radius 3 (ground)
28
+ :param depth: maximum depth
29
+ :param usable_width: usable width of the groove
30
+ :param pad_angle: angle between z-axis and the roll face padding
31
+ :param kwargs: more keyword arguments passed to the GenericElongationGroove constructor
32
+ """
33
+
34
+ pad_angle = np.deg2rad(pad_angle)
35
+
36
+ sol = solve_r123(r1, r2, r3, depth, usable_width, pad_angle)
37
+
38
+ super().__init__(
39
+ usable_width=usable_width, depth=depth,
40
+ r1=r1, r2=r2, r3=r3,
41
+ flank_angle=sol["flank_angle"], alpha3=sol["alpha3"], pad_angle=pad_angle,
42
+ **kwargs
43
+ )
44
+
45
+ @property
46
+ def classifiers(self):
47
+ return {"oval", "oval_3_radii"} | super().classifiers
@@ -0,0 +1,65 @@
1
+ from typing import Optional
2
+
3
+ import numpy as np
4
+ from scipy.optimize import brentq
5
+ from numpy import sin, cos, tan, pi
6
+
7
+ from ..generic_elongation import GenericElongationGroove
8
+ from ..generic_elongation_solvers import solve_r123
9
+
10
+
11
+ class Oval3RadiiFlankedGroove(GenericElongationGroove):
12
+ """Represents an oval-shaped groove with 3 main radii and a dedicated flank."""
13
+
14
+ def __init__(
15
+ self,
16
+ r1: float,
17
+ r2: float,
18
+ r3: float,
19
+ depth: float,
20
+ usable_width: float,
21
+ flank_angle: Optional[float] = None,
22
+ flank_width: Optional[float] = None,
23
+ flank_height: Optional[float] = None,
24
+ flank_length: Optional[float] = None,
25
+ pad_angle: float = 0,
26
+ **kwargs
27
+ ):
28
+ """
29
+ Widths are always measured at the intersection of the extrapolated ground, face and flanks.
30
+ All angles are measured in ° (degree).
31
+
32
+ :param r1: radius 1 (face/flank)
33
+ :param r2: radius 2 (flank/ground)
34
+ :param r3: radius 3 (ground)
35
+ :param depth: maximum depth
36
+ :param usable_width: usable width of the groove
37
+
38
+ :param flank_angle: inclination angle of the flanks
39
+ :param flank_width: horizontal extent of the flanks
40
+ :param flank_height: vertical extent of the flanks
41
+ :param flank_length: length of the flanks
42
+
43
+ :param pad_angle: angle between z-axis and the roll face padding
44
+ :param kwargs: more keyword arguments passed to the GenericElongationGroove constructor
45
+ """
46
+
47
+ if flank_angle is not None:
48
+ flank_angle = np.deg2rad(flank_angle)
49
+
50
+ pad_angle = np.deg2rad(pad_angle)
51
+
52
+ sol = solve_r123(
53
+ r1, r2, r3, depth, usable_width, pad_angle, flank_angle, flank_width, flank_height, flank_length
54
+ )
55
+
56
+ super().__init__(
57
+ usable_width=usable_width, depth=depth,
58
+ r1=r1, r2=r2, r3=r3,
59
+ flank_angle=sol["flank_angle"], alpha3=sol["alpha3"], pad_angle=pad_angle,
60
+ **kwargs
61
+ )
62
+
63
+ @property
64
+ def classifiers(self):
65
+ return {"oval", "oval_3_radii", "oval_3_radii_flanked"} | super().classifiers
@@ -0,0 +1,57 @@
1
+ from typing import Optional
2
+
3
+ import numpy as np
4
+
5
+ from ..generic_elongation import GenericElongationGroove
6
+ from ..generic_elongation_solvers import solve_box_like
7
+
8
+
9
+ class SwedishOvalGroove(GenericElongationGroove):
10
+ """Represents a hexagonal-shaped groove that is used like an oval groove (swedish oval)."""
11
+
12
+ def __init__(
13
+ self,
14
+ r1: float,
15
+ r2: float,
16
+ depth: float,
17
+ ground_width: Optional[float] = None,
18
+ even_ground_width: Optional[float] = None,
19
+ usable_width: Optional[float] = None,
20
+ flank_angle: Optional[float] = None,
21
+ pad_angle: float = 0,
22
+ **kwargs
23
+ ):
24
+ """
25
+ Exactly two of ``ground_width``, ``even_ground_width``, ``usable_width`` and ``flank_angle`` must be given,
26
+ but not ``ground_width`` and ``even_ground_width`` at the same time.
27
+ Widths are always measured at the intersection of the extrapolated ground, face and flanks.
28
+ All angles are measured in ° (degree).
29
+
30
+ :param r1: radius 1 (face/flank)
31
+ :param r2: radius 2 (flank/ground)
32
+ :param depth: maximum depth
33
+ :param ground_width: width of the groove ground
34
+ :param even_ground_width: width of the even ground line
35
+ :param usable_width: usable width of the groove
36
+ :param flank_angle: inclination angle of the flanks
37
+ :param pad_angle: angle between z-axis and the roll face padding
38
+ :param kwargs: more keyword arguments passed to the GenericElongationGroove constructor
39
+ :raises ValueError: if not exactly two of ground_width, usable_width and flank_angle are given
40
+ """
41
+ if flank_angle is not None:
42
+ flank_angle = np.deg2rad(flank_angle)
43
+
44
+ sol = solve_box_like(
45
+ r2=r2, r4=0, depth=depth, ground_width=ground_width, usable_width=usable_width, flank_angle=flank_angle,
46
+ indent=0, even_ground_width=even_ground_width
47
+ )
48
+
49
+ super().__init__(
50
+ r1=r1, r2=r2, pad_angle=np.deg2rad(pad_angle),
51
+ **sol,
52
+ **kwargs
53
+ )
54
+
55
+ @property
56
+ def classifiers(self):
57
+ return {"oval", "swedish_oval"} | super().classifiers
@@ -0,0 +1,47 @@
1
+ import numpy as np
2
+ from ..generic_elongation import GenericElongationGroove
3
+ from ..generic_elongation_solvers import solve_r123
4
+
5
+
6
+ class UpsetOvalGroove(GenericElongationGroove):
7
+ """Represents an upright oval-shaped groove."""
8
+
9
+ def __init__(
10
+ self,
11
+ r1: float,
12
+ r2: float,
13
+ r3: float,
14
+ depth: float,
15
+ usable_width: float,
16
+ pad_angle: float = 0,
17
+ **kwargs
18
+ ):
19
+ """
20
+ Widths are always measured at the intersection of the extrapolated ground, face and flanks.
21
+
22
+ :param r1: radius 1 (face/flank)
23
+ :param r2: radius 2 (flank/ground)
24
+ :param r3: radius 3 (ground)
25
+ :param depth: maximum depth
26
+ :param usable_width: usable width of the groove
27
+ :param kwargs: more keyword arguments passed to the GenericElongationGroove constructor
28
+ :param pad_angle: angle between z-axis and the roll face padding
29
+ """
30
+
31
+ pad_angle = np.deg2rad(pad_angle)
32
+
33
+ sol = solve_r123(r1, r2, r3, depth, usable_width, pad_angle)
34
+
35
+ if sol["flank_angle"] > np.pi / 2:
36
+ raise ValueError("under the given conditions the flank angle is > 90°")
37
+
38
+ super().__init__(
39
+ usable_width=usable_width, depth=depth,
40
+ r1=r1, r2=r2, r3=r3,
41
+ flank_angle=sol["flank_angle"], alpha3=sol["alpha3"], pad_angle=pad_angle,
42
+ **kwargs
43
+ )
44
+
45
+ @property
46
+ def classifiers(self):
47
+ return {"oval", "upset"} | super().classifiers
@@ -0,0 +1,2 @@
1
+ from .round import RoundGroove
2
+ from .false_round import FalseRoundGroove
@@ -0,0 +1,65 @@
1
+ from typing import Optional
2
+
3
+ import numpy as np
4
+
5
+ from ..generic_elongation import GenericElongationGroove
6
+ from ..generic_elongation_solvers import solve_r124
7
+
8
+
9
+ class FalseRoundGroove(GenericElongationGroove):
10
+ """Represents a round-shaped groove with a dedicated flank (false round)."""
11
+
12
+ def __init__(
13
+ self,
14
+ r1: float,
15
+
16
+ r2: Optional[float] = None,
17
+ depth: Optional[float] = None,
18
+ usable_width: Optional[float] = None,
19
+
20
+ flank_angle: Optional[float] = None,
21
+ flank_width: Optional[float] = None,
22
+ flank_height: Optional[float] = None,
23
+ flank_length: Optional[float] = None,
24
+
25
+ pad_angle: float = 0,
26
+ **kwargs
27
+ ):
28
+ """
29
+ All angles are measured in ° (degree).
30
+ Give exactly two of ``r2``, ``depth`` or ``usable_width``.
31
+ Give exactly one of ``flank_angle``, ``flank_width``, ``flank_height`` or ``flank_length``.
32
+
33
+ :param r1: radius 1 (face/flank)
34
+ :param r2: radius 2 (flank/ground)
35
+ :param depth: maximum depth
36
+ :param usable_width: usable width
37
+
38
+ :param flank_angle: inclination angle of the flanks
39
+ :param flank_width: horizontal extent of the flanks
40
+ :param flank_height: vertical extent of the flanks
41
+ :param flank_length: length of the flanks
42
+ :param pad_angle: angle between z-axis and the roll face padding
43
+ :param kwargs: more keyword arguments passed to the GenericElongationGroove constructor
44
+ """
45
+ pad_angle = np.deg2rad(pad_angle)
46
+
47
+ if flank_angle is not None:
48
+ flank_angle = np.deg2rad(flank_angle)
49
+
50
+ sol = solve_r124(
51
+ r1=r1,
52
+ r2=r2, depth=depth, width=usable_width,
53
+ pad_angle=pad_angle,
54
+ flank_angle=flank_angle, flank_width=flank_width, flank_height=flank_height, flank_length=flank_length
55
+ )
56
+
57
+ super().__init__(
58
+ r2=sol["r2"], depth=sol["depth"], usable_width=sol["width"], flank_angle=sol["alpha"],
59
+ r1=r1, pad_angle=pad_angle,
60
+ **kwargs
61
+ )
62
+
63
+ @property
64
+ def classifiers(self):
65
+ return {"round", "false_round"} | super().classifiers
@@ -0,0 +1,44 @@
1
+ from typing import Optional
2
+
3
+ import numpy as np
4
+ from scipy.optimize import root_scalar, minimize_scalar
5
+
6
+ from ..generic_elongation import GenericElongationGroove
7
+ from ..generic_elongation_solvers import solve_r124
8
+
9
+
10
+ class RoundGroove(GenericElongationGroove):
11
+ """Represents a round-shaped groove."""
12
+
13
+ def __init__(
14
+ self,
15
+ r1: float,
16
+ r2: Optional[float] = None,
17
+ depth: Optional[float] = None,
18
+ usable_width: Optional[float] = None,
19
+ pad_angle: float = 0,
20
+ **kwargs
21
+ ):
22
+ """
23
+ Give exactly two of ``r2``, ``depth`` or ``usable_width``.
24
+
25
+ :param r1: radius 1 (face/flank)
26
+ :param r2: radius 2 (flank/ground)
27
+ :param depth: maximum depth
28
+ :param usable_width: usable width
29
+ :param pad_angle: angle between z-axis and the roll face padding
30
+ :param kwargs: more keyword arguments passed to the GenericElongationGroove constructor
31
+ """
32
+ pad_angle = np.deg2rad(pad_angle)
33
+
34
+ sol = solve_r124(r1=r1, r2=r2, depth=depth, width=usable_width, pad_angle=pad_angle)
35
+
36
+ super().__init__(
37
+ r2=sol["r2"], depth=sol["depth"], usable_width=sol["width"], flank_angle=sol["alpha"],
38
+ r1=r1, pad_angle=pad_angle,
39
+ **kwargs
40
+ )
41
+
42
+ @property
43
+ def classifiers(self):
44
+ return {"round",} | super().classifiers