pyroll-core 3.1.0__tar.gz → 3.1.2__tar.gz
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.
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/PKG-INFO +1 -1
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/__init__.py +2 -2
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/disk_elements/hookimpls.py +8 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/engine/engine.py +13 -4
- pyroll_core-3.1.2/pyroll/core/engine/hookimpls.py +29 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/grooves/generic_elongation.py +2 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/grooves/ovals/constricted_swedish_oval.py +1 -1
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/profile/profile.py +31 -25
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/roll_pass/hookimpls/base_roll_pass.py +4 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/roll_pass/hookimpls/engine.py +7 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/roll_pass/hookimpls/profile.py +4 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/sequence/sequence.py +108 -12
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/unit/hookimpls.py +5 -0
- pyroll_core-3.1.0/pyroll/core/engine/hookimpls.py +0 -19
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/.gitignore +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/LICENSE +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/README.md +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/hatch.toml +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyproject.toml +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/config.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/disk_elements/__init__.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/disk_elements/disk_element_unit.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/engine/__init__.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/grooves/__init__.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/grooves/base.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/grooves/boxes/__init__.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/grooves/boxes/box.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/grooves/boxes/constricted_box.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/grooves/boxes/upset_box.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/grooves/diamonds/__init__.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/grooves/diamonds/diamond.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/grooves/diamonds/gothic.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/grooves/diamonds/square.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/grooves/equivalent_ripped_groove.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/grooves/flat.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/grooves/generic_elongation_solvers.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/grooves/hexagonal.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/grooves/ovals/__init__.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/grooves/ovals/circular_oval.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/grooves/ovals/constricted_circular_oval.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/grooves/ovals/flat_oval.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/grooves/ovals/oval_3radii.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/grooves/ovals/oval_3radii_flanked.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/grooves/ovals/swedish_oval.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/grooves/ovals/upset_oval.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/grooves/rounds/__init__.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/grooves/rounds/false_round.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/grooves/rounds/round.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/grooves/spline.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/hooks.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/log.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/profile/__init__.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/profile/hookimpls.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/repr.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/roll/__init__.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/roll/hookimpls.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/roll/roll.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/roll_pass/__init__.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/roll_pass/base.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/roll_pass/deformation_unit.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/roll_pass/hookimpls/__init__.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/roll_pass/hookimpls/deformation_unit.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/roll_pass/hookimpls/disk_element.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/roll_pass/hookimpls/helpers.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/roll_pass/hookimpls/roll.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/roll_pass/hookimpls/symmetric_roll_pass.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/roll_pass/hookimpls/three_roll_pass.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/roll_pass/hookimpls/two_roll_pass.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/roll_pass/symmetric_roll_pass.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/roll_pass/three_roll_pass.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/roll_pass/two_roll_pass.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/rotator/__init__.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/rotator/hookimpls.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/rotator/rotator.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/sequence/__init__.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/sequence/hookimpls.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/shapes.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/transport/__init__.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/transport/cooling_pipe.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/transport/hookimpls/__init__.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/transport/hookimpls/cooling_pipe.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/transport/hookimpls/transport.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/transport/transport.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/unit/__init__.py +0 -0
- {pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/unit/unit.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyroll-core
|
|
3
|
-
Version: 3.1.
|
|
3
|
+
Version: 3.1.2
|
|
4
4
|
Summary: PyRoll rolling simulation framework - core library.
|
|
5
5
|
Project-URL: Homepage, https://pyroll-project.github.io
|
|
6
6
|
Project-URL: Repository, https://github.com/pyroll-project/pyroll-core
|
|
@@ -45,7 +45,7 @@ from .hooks import Hook, HookHost, HookFunction, root_hooks
|
|
|
45
45
|
from .disk_elements import DiskElementUnit
|
|
46
46
|
from .config import Config, config, PlottingBackend, ConfigValue, ConfigMeta
|
|
47
47
|
|
|
48
|
-
VERSION = "3.1.
|
|
48
|
+
VERSION = "3.1.2"
|
|
49
49
|
|
|
50
50
|
__all__ = [
|
|
51
51
|
# grooves
|
|
@@ -134,6 +134,6 @@ root_hooks.extend(
|
|
|
134
134
|
BaseRollPass.InProfile.velocity,
|
|
135
135
|
PassSequence.log_elongation,
|
|
136
136
|
BaseRollPass.OutProfile.technologically_orientated_cross_section,
|
|
137
|
-
BaseRollPass.technologically_orientated_contour_lines
|
|
137
|
+
BaseRollPass.technologically_orientated_contour_lines,
|
|
138
138
|
]
|
|
139
139
|
)
|
|
@@ -24,3 +24,11 @@ def in_x(self: DiskElementUnit.DiskElement.InProfile):
|
|
|
24
24
|
except IndexError:
|
|
25
25
|
# is first disk: get from parent in_profile
|
|
26
26
|
return self.disk_element.parent.in_profile.x
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@DiskElementUnit.DiskElement.InProfile.position
|
|
30
|
+
def in_position(self: DiskElementUnit.DiskElement.InProfile):
|
|
31
|
+
try:
|
|
32
|
+
return self.disk_element.prev.out_profile.position
|
|
33
|
+
except IndexError:
|
|
34
|
+
return self.disk_element.parent.in_profile.position
|
|
@@ -10,9 +10,18 @@ __all__ = ["Engine"]
|
|
|
10
10
|
class Engine(HookHost):
|
|
11
11
|
"""Represents an engine of a roll pass."""
|
|
12
12
|
|
|
13
|
+
label = Hook[str]()
|
|
14
|
+
"""Type of the engine (DC or AC)"""
|
|
15
|
+
|
|
13
16
|
rotational_frequency = Hook[float]()
|
|
14
17
|
"""Rotational frequency (revolutions per time)."""
|
|
15
18
|
|
|
19
|
+
base_rotational_frequency = Hook[float]()
|
|
20
|
+
"""Knee point were a DC engine switches from anchor range to field weakening range."""
|
|
21
|
+
|
|
22
|
+
maximum_rotational_frequency = Hook[float]()
|
|
23
|
+
"""Maximum rotational frequency of the engine."""
|
|
24
|
+
|
|
16
25
|
torque = Hook[float]()
|
|
17
26
|
"""Engine torque."""
|
|
18
27
|
|
|
@@ -34,11 +43,11 @@ class Engine(HookHost):
|
|
|
34
43
|
maximum_power = Hook[float]()
|
|
35
44
|
"""Maximum power of the engine."""
|
|
36
45
|
|
|
37
|
-
|
|
38
|
-
"""
|
|
46
|
+
available_power = Hook[float]()
|
|
47
|
+
"""Available power of the engine only relevant for DC engines."""
|
|
39
48
|
|
|
40
|
-
|
|
41
|
-
"""
|
|
49
|
+
mean_power = Hook[float]()
|
|
50
|
+
"""Mean power of the engine incorporating roll pass and transport durations."""
|
|
42
51
|
|
|
43
52
|
|
|
44
53
|
def __init__(self, **kwargs):
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from .engine import Engine
|
|
4
|
+
from ..transport import Transport
|
|
5
|
+
|
|
6
|
+
@Engine.gear_box_efficiency
|
|
7
|
+
def gear_box_efficiency_becker(self: Engine):
|
|
8
|
+
return 0.95
|
|
9
|
+
|
|
10
|
+
@Engine.spindle_efficiency
|
|
11
|
+
def spindle_efficiency_becker(self: Engine):
|
|
12
|
+
return 0.98
|
|
13
|
+
|
|
14
|
+
@Engine.idle_torque
|
|
15
|
+
def default_idle_torque(self: Engine):
|
|
16
|
+
return 0
|
|
17
|
+
|
|
18
|
+
@Engine.power
|
|
19
|
+
def roll_power(self: Engine):
|
|
20
|
+
return self.torque * self.rotational_frequency * 2 * np.pi
|
|
21
|
+
|
|
22
|
+
@Engine.mean_power
|
|
23
|
+
def mean_power(self: Engine):
|
|
24
|
+
try:
|
|
25
|
+
next_transport = self.roll_pass.next_of(Transport)
|
|
26
|
+
except (IndexError, ValueError):
|
|
27
|
+
return np.sqrt(self.torque ** 2 * self.roll_pass.duration / self.roll_pass.duration)
|
|
28
|
+
|
|
29
|
+
return np.sqrt(self.torque ** 2 * self.roll_pass.duration / (next_transport.duration + self.roll_pass.duration))
|
|
@@ -31,6 +31,7 @@ class GenericElongationGroove(GrooveBase, ReprMixin):
|
|
|
31
31
|
rel_pad: float = Config.GROOVE_PADDING,
|
|
32
32
|
pad_angle: float = 0,
|
|
33
33
|
classifiers: Sequence[str] = (),
|
|
34
|
+
label: str = ""
|
|
34
35
|
):
|
|
35
36
|
"""
|
|
36
37
|
Give any three of ``usable_width``, ``ground_width``, ``flank_angle`` and ``depth``.
|
|
@@ -99,6 +100,7 @@ class GenericElongationGroove(GrooveBase, ReprMixin):
|
|
|
99
100
|
except TypeError:
|
|
100
101
|
raise TypeError("Exactly three of usable_width, ground_width, flank_angle and depth must be given.")
|
|
101
102
|
|
|
103
|
+
self.label = label
|
|
102
104
|
self.r1 = r1
|
|
103
105
|
self.r2 = r2
|
|
104
106
|
self.r3 = r3
|
|
@@ -32,11 +32,17 @@ class Profile(HookHost):
|
|
|
32
32
|
classifiers = Hook[Set[str]]()
|
|
33
33
|
"""Classifiers of the profile's shape's type."""
|
|
34
34
|
|
|
35
|
+
position = Hook[float]()
|
|
36
|
+
"""Global spacial coordinate in rolling direction."""
|
|
37
|
+
|
|
38
|
+
time = Hook[float]()
|
|
39
|
+
"""Global time in rolling direction."""
|
|
40
|
+
|
|
35
41
|
x = Hook[float]()
|
|
36
|
-
"""
|
|
42
|
+
"""Local spacial coordinate in rolling direction."""
|
|
37
43
|
|
|
38
44
|
t = Hook[float]()
|
|
39
|
-
"""
|
|
45
|
+
"""Local temporal coordinate."""
|
|
40
46
|
|
|
41
47
|
velocity = Hook[float]()
|
|
42
48
|
"""Mean material flow velocity."""
|
|
@@ -191,13 +197,13 @@ class Profile(HookHost):
|
|
|
191
197
|
|
|
192
198
|
@classmethod
|
|
193
199
|
def from_groove(
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
200
|
+
cls,
|
|
201
|
+
groove: GrooveBase,
|
|
202
|
+
width: Optional[float] = None,
|
|
203
|
+
filling: Optional[float] = None,
|
|
204
|
+
height: Optional[float] = None,
|
|
205
|
+
gap: Optional[float] = None,
|
|
206
|
+
**kwargs,
|
|
201
207
|
) -> "Profile":
|
|
202
208
|
"""
|
|
203
209
|
Create a profile instance based on a given groove.
|
|
@@ -242,8 +248,8 @@ class Profile(HookHost):
|
|
|
242
248
|
poly = Polygon(np.concatenate([upper_contour_line.coords, lower_contour_line.coords]))
|
|
243
249
|
|
|
244
250
|
if (
|
|
245
|
-
|
|
246
|
-
|
|
251
|
+
# one percent tolerance to bypass discretization issues
|
|
252
|
+
-width / 2 < poly.bounds[0] * 1.01 or width / 2 > poly.bounds[2] * 1.01
|
|
247
253
|
):
|
|
248
254
|
raise ValueError(
|
|
249
255
|
"Profile's width can not be larger than its contour lines." "May be caused by critical overfilling."
|
|
@@ -294,7 +300,7 @@ class Profile(HookHost):
|
|
|
294
300
|
|
|
295
301
|
@classmethod
|
|
296
302
|
def square(
|
|
297
|
-
|
|
303
|
+
cls, side: Optional[float] = None, diagonal: Optional[float] = None, corner_radius: float = 0, **kwargs
|
|
298
304
|
) -> "SquareProfile":
|
|
299
305
|
"""
|
|
300
306
|
Creates a square shaped profile (a real square with rounded corners, without imperfections of square grooves).
|
|
@@ -347,12 +353,12 @@ class Profile(HookHost):
|
|
|
347
353
|
|
|
348
354
|
@classmethod
|
|
349
355
|
def hexagon(
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
+
cls,
|
|
357
|
+
side: Optional[float] = None,
|
|
358
|
+
height: Optional[float] = None,
|
|
359
|
+
diagonal: Optional[float] = None,
|
|
360
|
+
corner_radius: float = 0,
|
|
361
|
+
**kwargs,
|
|
356
362
|
) -> "HexagonProfile":
|
|
357
363
|
"""
|
|
358
364
|
Creates a hexagonal shaped profile (a real hexagonal shape with rounded corners,
|
|
@@ -567,7 +573,7 @@ class DiamondProfile(Profile):
|
|
|
567
573
|
|
|
568
574
|
class SquareProfile(Profile):
|
|
569
575
|
def __init__(
|
|
570
|
-
|
|
576
|
+
self, side: Optional[float] = None, diagonal: Optional[float] = None, corner_radius: float = 0, **kwargs
|
|
571
577
|
):
|
|
572
578
|
"""
|
|
573
579
|
Creates a square shaped profile (a real square with rounded corners, without imperfections of square grooves).
|
|
@@ -626,12 +632,12 @@ class SquareProfile(Profile):
|
|
|
626
632
|
|
|
627
633
|
class HexagonProfile(Profile):
|
|
628
634
|
def __init__(
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
+
self,
|
|
636
|
+
side: Optional[float] = None,
|
|
637
|
+
height: Optional[float] = None,
|
|
638
|
+
diagonal: Optional[float] = None,
|
|
639
|
+
corner_radius: float = 0,
|
|
640
|
+
**kwargs,
|
|
635
641
|
):
|
|
636
642
|
"""
|
|
637
643
|
Creates a hexagonal shaped profile (a real hexagonal shape with rounded corners,
|
|
@@ -135,6 +135,10 @@ def default_back_tension(self: BaseRollPass):
|
|
|
135
135
|
def technologically_correctly_orientated_contour_lines(self: BaseRollPass):
|
|
136
136
|
return MultiLineString([self._get_oriented_geom(cl) for cl in self.contour_lines.geoms])
|
|
137
137
|
|
|
138
|
+
@BaseRollPass.InProfile.technologically_orientated_cross_section
|
|
139
|
+
def technologically_correctly_orientated_cross_section(self: BaseRollPass.InProfile):
|
|
140
|
+
return self.roll_pass._get_oriented_geom(self.cross_section, orientation=self.roll_pass.orientation)
|
|
141
|
+
|
|
138
142
|
|
|
139
143
|
@BaseRollPass.OutProfile.technologically_orientated_cross_section
|
|
140
144
|
def technologically_correctly_orientated_cross_section(self: BaseRollPass.OutProfile):
|
|
@@ -19,3 +19,10 @@ def engine_rotational_frequency(self: BaseRollPass.Engine):
|
|
|
19
19
|
return self.roll_pass.roll.rotational_frequency * self.gear_ratio
|
|
20
20
|
else:
|
|
21
21
|
return self.roll_pass.roll.rotational_frequency
|
|
22
|
+
|
|
23
|
+
@BaseRollPass.Engine.available_power
|
|
24
|
+
def available_power(self: BaseRollPass.Engine):
|
|
25
|
+
if self.has_set_or_cached("base_rotational_frequency"):
|
|
26
|
+
return self.maximum_power * (self.rotational_frequency / self.base_rotational_frequency)
|
|
27
|
+
else:
|
|
28
|
+
return self.maximum_power
|
|
@@ -75,6 +75,10 @@ def cross_section(self: BaseRollPass.OutProfile) -> Polygon:
|
|
|
75
75
|
if width_at_y0 < in_profile_width:
|
|
76
76
|
in_profile_width = width_at_y0
|
|
77
77
|
|
|
78
|
+
if "constricted" in self.roll_pass.classifiers:
|
|
79
|
+
cs = helpers.out_cross_section(self.roll_pass, self.width)
|
|
80
|
+
return cs
|
|
81
|
+
|
|
78
82
|
half_abs_spread = (self.width - in_profile_width) / 2
|
|
79
83
|
half_in_profile = clip_by_rect(self.roll_pass.in_profile.cross_section, 0, -np.inf, np.inf, np.inf)
|
|
80
84
|
out_profile_side_contour_translated = translate(half_in_profile, xoff=half_abs_spread)
|
|
@@ -4,7 +4,9 @@ import numpy as np
|
|
|
4
4
|
|
|
5
5
|
from collections.abc import Sequence
|
|
6
6
|
from typing import overload, List, cast
|
|
7
|
+
from scipy.interpolate import interp1d
|
|
7
8
|
|
|
9
|
+
from .. import CoolingPipe
|
|
8
10
|
from ..unit import Unit
|
|
9
11
|
from ..roll_pass import BaseRollPass
|
|
10
12
|
from ..transport import Transport
|
|
@@ -130,6 +132,11 @@ class PassSequence(Unit, Sequence[Unit]):
|
|
|
130
132
|
"""Returns a list of all transports in this sequence."""
|
|
131
133
|
return list(u for u in self._subunits if isinstance(u, Transport))
|
|
132
134
|
|
|
135
|
+
@property
|
|
136
|
+
def cooling_pipes(self) -> List[CoolingPipe]:
|
|
137
|
+
"""Returns a list of all cooling pipes in this sequence."""
|
|
138
|
+
return list(u for u in self._subunits if isinstance(u, CoolingPipe))
|
|
139
|
+
|
|
133
140
|
@property
|
|
134
141
|
def __attrs__(self):
|
|
135
142
|
return super().__attrs__ | {"units": self.units}
|
|
@@ -137,6 +144,32 @@ class PassSequence(Unit, Sequence[Unit]):
|
|
|
137
144
|
def _ipython_key_completions_(self):
|
|
138
145
|
return [u.label for u in self._subunits]
|
|
139
146
|
|
|
147
|
+
def solve_velocities_from_elongations(self, in_profile: Profile, final_speed: float, elongations: np.ndarray):
|
|
148
|
+
"""
|
|
149
|
+
Solve method, that calculates all velocities of the roll pass starting from the very last roll_pass of the sequence using given elongations.
|
|
150
|
+
|
|
151
|
+
:param in_profile: incoming profile
|
|
152
|
+
:param final_speed: speed of the last stand
|
|
153
|
+
:param elongations: array of the elongations per pass, starting from the first roll pass
|
|
154
|
+
"""
|
|
155
|
+
|
|
156
|
+
if len(elongations) != len(self.roll_passes) - 1:
|
|
157
|
+
raise ValueError("Number of Elongations doesn't match the number of roll passes.")
|
|
158
|
+
|
|
159
|
+
speed = final_speed
|
|
160
|
+
speeds = [final_speed]
|
|
161
|
+
|
|
162
|
+
for e in elongations:
|
|
163
|
+
speed = speed / e
|
|
164
|
+
speeds.append(speed)
|
|
165
|
+
|
|
166
|
+
speeds = np.array(speeds)
|
|
167
|
+
|
|
168
|
+
for rp, speed in zip(self.roll_passes, speeds[::-1]):
|
|
169
|
+
rp.velocity = speed
|
|
170
|
+
|
|
171
|
+
self.solve(in_profile)
|
|
172
|
+
|
|
140
173
|
def solve_velocities_backward(self, in_profile: Profile, final_speed: float, final_cross_section_area: float):
|
|
141
174
|
"""
|
|
142
175
|
Solve method, that calculates all velocities of the roll pass starting from the very last roll_pass of the sequence.
|
|
@@ -156,13 +189,17 @@ class PassSequence(Unit, Sequence[Unit]):
|
|
|
156
189
|
for roll_pass, velocity in zip(roll_passes, velocities):
|
|
157
190
|
roll_pass.velocity = velocity
|
|
158
191
|
|
|
159
|
-
usable_cross_section_areas = np.asarray(
|
|
192
|
+
usable_cross_section_areas = np.asarray(
|
|
193
|
+
[roll_pass.usable_cross_section.area for roll_pass in copied_sequence.roll_passes]
|
|
194
|
+
)
|
|
160
195
|
initial_roll_pass_velocities = np.zeros_like(usable_cross_section_areas, dtype=float)
|
|
161
196
|
|
|
162
197
|
initial_roll_pass_velocities[-1] = final_speed
|
|
163
198
|
usable_cross_section_areas[-1] = final_cross_section_area
|
|
164
199
|
|
|
165
|
-
calculate_velocities_array(
|
|
200
|
+
calculate_velocities_array(
|
|
201
|
+
velocities=initial_roll_pass_velocities, cross_sections_areas=usable_cross_section_areas
|
|
202
|
+
)
|
|
166
203
|
set_velocities_to_roll_passes(roll_passes=copied_sequence.roll_passes, velocities=initial_roll_pass_velocities)
|
|
167
204
|
|
|
168
205
|
copied_sequence.solve(in_profile)
|
|
@@ -173,7 +210,9 @@ class PassSequence(Unit, Sequence[Unit]):
|
|
|
173
210
|
profile_areas = [roll_pass.out_profile.cross_section.area for roll_pass in copied_sequence.roll_passes]
|
|
174
211
|
|
|
175
212
|
calculate_velocities_array(velocities=current_roll_pass_velocities, cross_sections_areas=profile_areas)
|
|
176
|
-
set_velocities_to_roll_passes(
|
|
213
|
+
set_velocities_to_roll_passes(
|
|
214
|
+
roll_passes=copied_sequence.roll_passes, velocities=current_roll_pass_velocities
|
|
215
|
+
)
|
|
177
216
|
|
|
178
217
|
copied_sequence.solve(in_profile)
|
|
179
218
|
|
|
@@ -203,12 +242,18 @@ class PassSequence(Unit, Sequence[Unit]):
|
|
|
203
242
|
for roll_pass, velocity in zip(roll_passes, velocities):
|
|
204
243
|
roll_pass.velocity = velocity
|
|
205
244
|
|
|
206
|
-
usable_cross_section_areas = np.asarray(
|
|
245
|
+
usable_cross_section_areas = np.asarray(
|
|
246
|
+
[roll_pass.usable_cross_section.area for roll_pass in copied_sequence.roll_passes]
|
|
247
|
+
)
|
|
207
248
|
initial_roll_pass_velocities = np.zeros_like(usable_cross_section_areas, dtype=float)
|
|
208
249
|
|
|
209
|
-
initial_roll_pass_velocities[0] =
|
|
250
|
+
initial_roll_pass_velocities[0] = (
|
|
251
|
+
initial_speed * in_profile.cross_section.area / copied_sequence.roll_passes[0].usable_cross_section.area
|
|
252
|
+
)
|
|
210
253
|
|
|
211
|
-
calculate_velocities_array(
|
|
254
|
+
calculate_velocities_array(
|
|
255
|
+
velocities=initial_roll_pass_velocities, cross_sections_areas=usable_cross_section_areas
|
|
256
|
+
)
|
|
212
257
|
set_velocities_to_roll_passes(roll_passes=copied_sequence.roll_passes, velocities=initial_roll_pass_velocities)
|
|
213
258
|
|
|
214
259
|
copied_sequence.solve(in_profile)
|
|
@@ -231,8 +276,9 @@ class PassSequence(Unit, Sequence[Unit]):
|
|
|
231
276
|
self.solve(in_profile)
|
|
232
277
|
break
|
|
233
278
|
|
|
234
|
-
def solve_interstand_tensions_with_given_velocity_ratios(
|
|
235
|
-
|
|
279
|
+
def solve_interstand_tensions_with_given_velocity_ratios(
|
|
280
|
+
self, in_profile: Profile, velocity_ratios: np.ndarray[float], final_speed: float
|
|
281
|
+
):
|
|
236
282
|
"""
|
|
237
283
|
Solve method, that calculates the resulting tensions for given reductions.
|
|
238
284
|
Further, it sets the velocities according to these reductions and the finishing speed.
|
|
@@ -260,10 +306,12 @@ class PassSequence(Unit, Sequence[Unit]):
|
|
|
260
306
|
for index in range(1, len(self.roll_passes)):
|
|
261
307
|
engineering_strain = engineering_strains[index - 1]
|
|
262
308
|
|
|
263
|
-
tensions[2 * index - 1] =
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
309
|
+
tensions[2 * index - 1] = (
|
|
310
|
+
copied_sequence.roll_passes[index - 1].in_profile.elastic_modulus * engineering_strain
|
|
311
|
+
)
|
|
312
|
+
tensions[2 * index] -= (
|
|
313
|
+
copied_sequence.roll_passes[index - 1].out_profile.elastic_modulus * engineering_strain
|
|
314
|
+
)
|
|
267
315
|
|
|
268
316
|
tensions[0] = 0
|
|
269
317
|
tensions[-1] = 0
|
|
@@ -273,3 +321,51 @@ class PassSequence(Unit, Sequence[Unit]):
|
|
|
273
321
|
roll_pass.front_tension = tensions[2 * index + 1]
|
|
274
322
|
|
|
275
323
|
self.solve(in_profile=in_profile)
|
|
324
|
+
|
|
325
|
+
def find_value_by_position_or_time(self, hook_name: str, position: float = None, time: float = None):
|
|
326
|
+
if position is None:
|
|
327
|
+
search_coordinate = "t"
|
|
328
|
+
else:
|
|
329
|
+
search_coordinate = "position"
|
|
330
|
+
|
|
331
|
+
coordinates = []
|
|
332
|
+
values = []
|
|
333
|
+
|
|
334
|
+
for su in self.subunits:
|
|
335
|
+
if len(su.subunits) > 0:
|
|
336
|
+
for ssu in su.subunits:
|
|
337
|
+
coordinates.append(getattr(ssu.in_profile, search_coordinate, None))
|
|
338
|
+
values.append(getattr(ssu.in_profile, hook_name, None))
|
|
339
|
+
|
|
340
|
+
coordinates.append(getattr(ssu.out_profile, search_coordinate, None))
|
|
341
|
+
values.append(getattr(ssu.out_profile, hook_name, None))
|
|
342
|
+
else:
|
|
343
|
+
coordinates.append(getattr(su.in_profile, search_coordinate, None))
|
|
344
|
+
values.append(getattr(su.in_profile, hook_name, None))
|
|
345
|
+
|
|
346
|
+
coordinates.append(getattr(su.out_profile, search_coordinate, None))
|
|
347
|
+
values.append(getattr(su.out_profile, hook_name, None))
|
|
348
|
+
|
|
349
|
+
if all(v is None for v in values):
|
|
350
|
+
raise ValueError(f"No hook with name {hook_name} found.")
|
|
351
|
+
|
|
352
|
+
closest_pos = min(coordinates, key=lambda p: abs(p - position))
|
|
353
|
+
closest_index = coordinates.index(closest_pos)
|
|
354
|
+
|
|
355
|
+
postion_array = np.array(coordinates)
|
|
356
|
+
values_array = np.array(values)
|
|
357
|
+
|
|
358
|
+
next_element = 1
|
|
359
|
+
while True:
|
|
360
|
+
if (closest_index + next_element) >= len(coordinates):
|
|
361
|
+
raise ValueError(f"Coordinate index {closest_index + next_element} out of sequence range.")
|
|
362
|
+
|
|
363
|
+
if coordinates[closest_index + next_element] >= position:
|
|
364
|
+
break
|
|
365
|
+
next_element += 1
|
|
366
|
+
|
|
367
|
+
val = values_array[closest_index : closest_index + next_element + 1]
|
|
368
|
+
pos = postion_array[closest_index : closest_index + next_element + 1]
|
|
369
|
+
interpolation = interp1d(pos, val)
|
|
370
|
+
|
|
371
|
+
return interpolation(position)
|
|
@@ -56,6 +56,11 @@ def out_velocity(self: Unit.OutProfile):
|
|
|
56
56
|
return self.unit.in_profile.velocity * self.unit.in_profile.cross_section.area / self.cross_section.area
|
|
57
57
|
|
|
58
58
|
|
|
59
|
+
@Unit.OutProfile.position
|
|
60
|
+
def out_position(self: Unit.OutProfile):
|
|
61
|
+
return self.unit.in_profile.position + self.unit.length
|
|
62
|
+
|
|
63
|
+
|
|
59
64
|
@Unit.OutProfile.x
|
|
60
65
|
def out_x(self: Unit.OutProfile):
|
|
61
66
|
return self.unit.in_profile.x + self.unit.length
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import numpy as np
|
|
2
|
-
|
|
3
|
-
from .engine import Engine
|
|
4
|
-
|
|
5
|
-
@Engine.gear_box_efficiency
|
|
6
|
-
def gear_box_efficiency_becker(self: Engine):
|
|
7
|
-
return 0.95
|
|
8
|
-
|
|
9
|
-
@Engine.spindle_efficiency
|
|
10
|
-
def spindle_efficiency_becker(self: Engine):
|
|
11
|
-
return 0.98
|
|
12
|
-
|
|
13
|
-
@Engine.idle_torque
|
|
14
|
-
def default_idle_torque(self: Engine):
|
|
15
|
-
return 0
|
|
16
|
-
|
|
17
|
-
@Engine.power
|
|
18
|
-
def roll_power(self: Engine):
|
|
19
|
-
return self.torque * self.rotational_frequency * 2 * np.pi
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/grooves/ovals/constricted_circular_oval.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyroll_core-3.1.0 → pyroll_core-3.1.2}/pyroll/core/roll_pass/hookimpls/symmetric_roll_pass.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|