Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

104 add second working roll #251

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion pyroll/core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from .grooves import *
from .transport import Transport, CoolingPipe
from .roll_pass import BaseRollPass, RollPass, DeformationUnit, ThreeRollPass
from .roll_pass import BaseRollPass, RollPass, DeformationUnit, ThreeRollPass, AsymmetricTwoRollPass
from .unit import Unit
from .roll import Roll
from .profile import *
Expand All @@ -16,6 +16,8 @@

root_hooks.extend(
[
AsymmetricTwoRollPass.InProfile.pass_line,
AsymmetricTwoRollPass.InProfile.cross_section,
BaseRollPass.roll_force,
BaseRollPass.Roll.roll_torque,
BaseRollPass.elongation_efficiency,
Expand Down
2 changes: 1 addition & 1 deletion pyroll/core/roll/hookimpls.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def contour_points(self: Roll):

@Roll.surface_x
def surface_x(self: Roll):
padded_contact_angle = np.arcsin(1.1 * self.contact_length / self.min_radius)
padded_contact_angle = np.arcsin(1.1 * self.contact_length / self.min_radius) if self.has_set_or_cached("contact_length") else np.pi / 4
points = np.concatenate([
np.linspace(0, padded_contact_angle, Config.ROLL_SURFACE_DISCRETIZATION_COUNT, endpoint=False),
np.linspace(padded_contact_angle, np.pi / 2, Config.ROLL_SURFACE_DISCRETIZATION_COUNT),
Expand Down
5 changes: 4 additions & 1 deletion pyroll/core/roll_pass/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
from .base import BaseRollPass
from .roll_pass import RollPass
from .two_roll_pass import TwoRollPass
from .asymmetric_two_roll_pass import AsymmetricTwoRollPass
from .three_roll_pass import ThreeRollPass
from .deformation_unit import DeformationUnit

from . import hookimpls

RollPass = TwoRollPass



114 changes: 114 additions & 0 deletions pyroll/core/roll_pass/asymmetric_two_roll_pass.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
from typing import List, cast

import numpy as np
from shapely.affinity import translate, scale
from shapely.geometry import LineString

from .base import BaseRollPass
from ..hooks import Hook
from ..roll import Roll as BaseRoll


class AsymmetricTwoRollPass(BaseRollPass):
"""Represents a symmetric roll pass with equal upper and lower working roll."""

def __init__(
self,
upper_roll: BaseRoll,
lower_roll: BaseRoll,
label: str = "",
**kwargs
):
super().__init__(label, **kwargs)

self.upper_roll = self.Roll(upper_roll, self)
"""The upper working roll of this pass."""

self.lower_roll = self.Roll(lower_roll, self)
"""The upper working roll of this pass."""

@property
def contour_lines(self) -> List[LineString]:
if self._contour_lines:
return self._contour_lines

upper = translate(self.upper_roll.contour_line, yoff=self.gap / 2)
lower = scale(
translate(self.lower_roll.contour_line.reverse(), yoff=self.gap / 2),
xfact=1, yfact=-1, origin=(0, 0)
)

self._contour_lines = [upper, lower]
return self._contour_lines

@property
def classifiers(self):
"""A tuple of keywords to specify the shape type classifiers of this roll pass.
Shortcut to ``self.groove.classifiers``."""
return set(self.upper_roll.groove.classifiers) | set(self.lower_roll.groove.classifiers) | {"asymmetric"}

@property
def disk_elements(self) -> List['AsymmetricTwoRollPass.DiskElement']:
"""A list of disk elements used to subdivide this unit."""
return list(self._subunits)

def get_root_hook_results(self):
super_results = super().get_root_hook_results()
upper_roll_results = self.upper_roll.evaluate_and_set_hooks()
lower_roll_results = self.lower_roll.evaluate_and_set_hooks()
return np.concatenate([super_results, upper_roll_results, lower_roll_results], axis=0)

def reevaluate_cache(self):
super().reevaluate_cache()
self.upper_roll.reevaluate_cache()
self.lower_roll.reevaluate_cache()
self._contour_lines = None

class Profile(BaseRollPass.Profile):
"""Represents a profile in context of a roll pass."""

@property
def roll_pass(self) -> 'AsymmetricTwoRollPass':
"""Reference to the roll pass. Alias for ``self.unit``."""
return cast(AsymmetricTwoRollPass, self.unit)

class InProfile(Profile, BaseRollPass.InProfile):
"""Represents an incoming profile of a roll pass."""

pass_line = Hook[tuple[float, float, float]]()
"""Point (x, y, z) where the incoming profile centroid enters the roll pass."""

class OutProfile(Profile, BaseRollPass.OutProfile):
"""Represents an outgoing profile of a roll pass."""

filling_ratio = Hook[float]()

class Roll(BaseRollPass.Roll):
"""Represents a roll applied in a :py:class:`RollPass`."""

@property
def roll_pass(self) -> 'AsymmetricTwoRollPass':
"""Reference to the roll pass."""
return cast(AsymmetricTwoRollPass, self._roll_pass())

class DiskElement(BaseRollPass.DiskElement):
"""Represents a disk element in a roll pass."""

@property
def roll_pass(self) -> 'AsymmetricTwoRollPass':
"""Reference to the roll pass. Alias for ``self.parent``."""
return cast(AsymmetricTwoRollPass, self.parent)

class Profile(BaseRollPass.DiskElement.Profile):
"""Represents a profile in context of a disk element unit."""

@property
def disk_element(self) -> 'AsymmetricTwoRollPass.DiskElement':
"""Reference to the disk element. Alias for ``self.unit``"""
return cast(AsymmetricTwoRollPass.DiskElement, self.unit)

class InProfile(Profile, BaseRollPass.DiskElement.InProfile):
"""Represents an incoming profile of a disk element unit."""

class OutProfile(Profile, BaseRollPass.DiskElement.OutProfile):
"""Represents an outgoing profile of a disk element unit."""
46 changes: 24 additions & 22 deletions pyroll/core/roll_pass/base.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import weakref
from abc import abstractmethod, ABC
from typing import List, Union, cast

import numpy as np
Expand All @@ -13,7 +14,7 @@
from .deformation_unit import DeformationUnit


class BaseRollPass(DiskElementUnit, DeformationUnit):
class BaseRollPass(DiskElementUnit, DeformationUnit, ABC):
"""Represents a roll pass with two symmetric working rolls."""

rotation = Hook[Union[bool, float]]()
Expand Down Expand Up @@ -63,15 +64,9 @@ class BaseRollPass(DiskElementUnit, DeformationUnit):
entry_point = Hook[float]()
"""Point where the material enters the roll gap."""

entry_angle = Hook[float]()
"""Angle at which the material enters the roll gap."""

exit_point = Hook[float]()
"""Point where the material exits the roll gap."""

exit_angle = Hook[float]()
"""Angle at which the material exits the roll gap."""

front_tension = Hook[float]()
"""Front tension acting on the current roll pass."""

Expand Down Expand Up @@ -104,7 +99,6 @@ class BaseRollPass(DiskElementUnit, DeformationUnit):

def __init__(
self,
roll: BaseRoll,
label: str = "",
**kwargs
):
Expand All @@ -116,28 +110,35 @@ def __init__(

super().__init__(label=label, **kwargs)

self.roll = self.Roll(roll, self)
"""The working roll of this pass (equal upper and lower)."""

self._contour_lines = None

self.given_in_profile: BaseProfile | None = None
"""The incoming profile as was given to the ``solve`` method."""

self.rotated_in_profile: BaseProfile | None = None
"""The incoming profile after rotation."""

@property
@abstractmethod
def contour_lines(self):
"""List of line strings bounding the roll pass at the high point."""
raise NotImplementedError
raise NotImplementedError()

@property
@abstractmethod
def classifiers(self):
"""A tuple of keywords to specify the shape type classifiers of this roll pass.
Shortcut to ``self.groove.classifiers``."""
return set(self.roll.groove.classifiers)
raise NotImplementedError()

@property
def disk_elements(self) -> List['BaseRollPass.DiskElement']:
"""A list of disk elements used to subdivide this unit."""
return list(self._subunits)

def init_solve(self, in_profile: BaseProfile):
self.given_in_profile = in_profile

if self.rotation:
rotator = Rotator(
# make True determining from hook functions
Expand All @@ -146,20 +147,15 @@ def init_solve(self, in_profile: BaseProfile):
duration=0, length=0, parent=self
)
rotator.solve(in_profile)
in_profile = rotator.out_profile
self.rotated_in_profile = rotator.out_profile
else:
self.rotated_in_profile = in_profile

super().init_solve(in_profile)
super().init_solve(self.rotated_in_profile)
self.out_profile.cross_section = self.usable_cross_section

def get_root_hook_results(self):
super_results = super().get_root_hook_results()
roll_results = self.roll.evaluate_and_set_hooks()

return np.concatenate([super_results, roll_results], axis=0)

def reevaluate_cache(self):
super().reevaluate_cache()
self.roll.reevaluate_cache()
self._contour_lines = None

class Profile(DiskElementUnit.Profile, DeformationUnit.Profile):
Expand Down Expand Up @@ -200,6 +196,12 @@ def __init__(self, template: BaseRoll, roll_pass: 'BaseRollPass'):

self._roll_pass = weakref.ref(roll_pass)

entry_angle = Hook[float]()
"""Angle at which the material enters the roll gap."""

exit_angle = Hook[float]()
"""Angle at which the material exits the roll gap."""

@property
def roll_pass(self):
"""Reference to the roll pass this roll is used in."""
Expand Down
6 changes: 5 additions & 1 deletion pyroll/core/roll_pass/hookimpls/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
from . import roll_pass
from . import base_roll_pass
from . import symmetric_roll_pass
from . import two_roll_pass
from . import asymmetric_two_roll_pass
from . import three_roll_pass
from . import profile
from . import roll
from . import disk_element
Expand Down
Loading