1
1
import numpy as np
2
+ import scipy .optimize
3
+ import shapely .affinity
2
4
from shapely import Polygon
3
5
4
6
from . import helpers
@@ -61,37 +63,6 @@ def roll_power(self: AsymmetricTwoRollPass):
61
63
return self .upper_roll .roll_power + self .lower_roll .roll_power
62
64
63
65
64
- @AsymmetricTwoRollPass .entry_point
65
- def entry_point (self : AsymmetricTwoRollPass ):
66
- height_change = self .in_profile .height - self .height
67
- return (
68
- np .sqrt (height_change )
69
- * np .sqrt (
70
- (2 * self .upper_roll .min_radius - height_change )
71
- * (2 * self .lower_roll .min_radius - height_change )
72
- * (2 * self .upper_roll .min_radius + 2 * self .lower_roll .min_radius - height_change )
73
- )
74
- ) / (2 * (self .upper_roll .min_radius + self .lower_roll .min_radius - height_change ))
75
-
76
-
77
- @AsymmetricTwoRollPass .entry_point
78
- def entry_point_square_oval (self : AsymmetricTwoRollPass ):
79
- if "square" in self .in_profile .classifiers and "oval" in self .classifiers :
80
- upper_depth = self .upper_roll .groove .local_depth (self .in_profile .width / 2 )
81
- lower_depth = self .lower_roll .groove .local_depth (self .in_profile .width / 2 )
82
- height_change = self .in_profile .height - self .gap - upper_depth - lower_depth
83
- upper_radius = self .upper_roll .max_radius - upper_depth
84
- lower_radius = self .lower_roll .max_radius - lower_depth
85
- return (
86
- np .sqrt (height_change )
87
- * np .sqrt (
88
- (2 * upper_radius - height_change )
89
- * (2 * lower_radius - height_change )
90
- * (2 * upper_radius + 2 * lower_radius - height_change )
91
- )
92
- ) / (2 * (upper_radius + lower_radius - height_change ))
93
-
94
-
95
66
@AsymmetricTwoRollPass .velocity
96
67
def velocity (self : AsymmetricTwoRollPass ):
97
68
if self .upper_roll .has_value ("neutral_angle" ) and self .lower_roll .has_value ("neutral_angle" ):
@@ -111,3 +82,59 @@ def roll_force(self: AsymmetricTwoRollPass):
111
82
* (self .upper_roll .contact_area + self .lower_roll .contact_area )
112
83
/ 2
113
84
)
85
+
86
+
87
+ @AsymmetricTwoRollPass .InProfile .pass_line
88
+ def pass_line (self : AsymmetricTwoRollPass .InProfile ) -> tuple [float , float , float ]:
89
+ rp = self .roll_pass
90
+
91
+ if not self .has_set ("pass_line" ):
92
+ height_change = self .height - rp .height
93
+ x_guess = - (
94
+ np .sqrt (height_change )
95
+ * np .sqrt (
96
+ (2 * rp .upper_roll .min_radius - height_change )
97
+ * (2 * rp .lower_roll .min_radius - height_change )
98
+ * (2 * rp .upper_roll .min_radius + 2 * rp .lower_roll .min_radius - height_change )
99
+ )
100
+ ) / (2 * (rp .upper_roll .min_radius + rp .lower_roll .min_radius - height_change ))
101
+ y_guess = 0
102
+ else :
103
+ x_guess , y_guess , _ = self .pass_line
104
+
105
+ def contact_objective (xy ):
106
+ shifted_cross_section = shapely .affinity .translate (rp .rotated_in_profile .cross_section , yoff = xy [1 ])
107
+
108
+ upper_contour = shapely .geometry .LineString (np .stack ([
109
+ rp .upper_roll .surface_z ,
110
+ rp .upper_roll .surface_interpolation (xy [0 ], rp .upper_roll .surface_z ).squeeze (axis = 1 )
111
+ ], axis = 1 ))
112
+ upper_contour = shapely .affinity .translate (upper_contour ,yoff = self .roll_pass .gap / 2 )
113
+ lower_contour = shapely .geometry .LineString (np .stack ([
114
+ rp .lower_roll .surface_z ,
115
+ rp .lower_roll .surface_interpolation (xy [0 ], rp .lower_roll .surface_z ).squeeze (axis = 1 )
116
+ ], axis = 1 ))
117
+ lower_contour = shapely .affinity .scale (shapely .affinity .translate (lower_contour , yoff = self .roll_pass .gap / 2 ), xfact = 1 , yfact = - 1 , origin = (0 ,0 ))
118
+
119
+ upper_intersection = shapely .intersection (upper_contour , shifted_cross_section )
120
+ lower_intersection = shapely .intersection (lower_contour , shifted_cross_section )
121
+
122
+ upper_value = upper_intersection .length if not upper_intersection .is_empty else shapely .shortest_line (upper_contour , shifted_cross_section ).length
123
+ lower_value = lower_intersection .length if not lower_intersection .is_empty else shapely .shortest_line (lower_contour , shifted_cross_section ).length
124
+
125
+ return upper_value ** 2 + lower_value ** 2
126
+
127
+ sol = scipy .optimize .minimize (contact_objective , (x_guess , y_guess ), method = "BFGS" , options = dict (xrtol = 1e-2 ))
128
+
129
+ return sol .x [0 ], sol .x [1 ], 0
130
+
131
+
132
+ @AsymmetricTwoRollPass .InProfile .cross_section
133
+ def in_cross_section (self :AsymmetricTwoRollPass .InProfile ):
134
+ return shapely .affinity .translate (self .roll_pass .rotated_in_profile .cross_section , xoff = self .pass_line [2 ], yoff = self .pass_line [1 ])
135
+
136
+
137
+ @AsymmetricTwoRollPass .entry_point
138
+ def entry_point (self : AsymmetricTwoRollPass ):
139
+ return self .in_profile .pass_line [0 ]
140
+
0 commit comments