Skip to content

Instantly share code, notes, and snippets.

@QiangF
Last active April 12, 2026 09:13
Show Gist options
  • Select an option

  • Save QiangF/667b8a26d7b6424b26889ed31b0512c3 to your computer and use it in GitHub Desktop.

Select an option

Save QiangF/667b8a26d7b6424b26889ed31b0512c3 to your computer and use it in GitHub Desktop.
import re
import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
import pyroll.core
import pyroll.pillar_model
import pyroll.freiberg_flow_stress
from pyroll.freiberg_flow_stress import FreibergFlowStressCoefficients
# import pyroll.hill_spreading
# import pyroll.roux_spreading
import pyroll.sander_spreading
# import pyroll.sparling_spreading
# import pyroll.marini_spreading
# import pyroll.lendl_equivalent_method
import pyroll.lippmann_mahrenholz_force_torque
import pyroll.zouhar_contact
import pyroll.integral_thermal
# import pyroll.wusatowski_spreading
# @pyroll.core.SymmetricRollPass.wusatowski_material_coefficient
# def wusatowski_material_coefficient(self):
# return 1
# @pyroll.core.SymmetricRollPass.wusatowski_friction_coefficient
# def wusatowski_friction_coefficient(self):
# return 1.001
# # return 1
# # return 0.995
def create_groove(groove_name, grooves):
groove = grooves.loc[groove_name]
groove_name = groove_name.lower().strip(' ')
groove_type = re.sub(r'[.\(\)\-0-9]', '', groove_name)
if groove_type == 'box':
shape = pyroll.core.BoxGroove(ground_width=groove['a'], usable_width=groove['A'], depth=groove['h'], r1=groove['r'], r2=groove['R'])
elif groove_type in ['ov', 'ova', 'ovc', 'ove', 'ovf']:
shape = pyroll.core.CircularOvalGroove(depth=groove['h'], r1=groove['r'], r2=groove['R'])
elif groove_type == 'ovp':
shape = pyroll.core.Oval3RadiiFlankedGroove(usable_width=groove['A'], depth=groove['h'], r1=groove['r'], r2=groove['R1'], r3=groove['R'], flank_angle=90 - groove['alpha'])
elif groove_type == 'r':
shape = pyroll.core.FalseRoundGroove(depth=groove['h'], r1=groove['r'], r2=groove['R'])
elif groove_name.startswith('rd2') or groove_name.startswith('frd') or groove_name.startswith('bo'):
shape = pyroll.core.Oval3RadiiGroove(usable_width=groove['A'], depth=groove['h'], r1=0.0, r2=groove['R1'], r3=groove['R'])
elif groove_type == 'rf':
shape = pyroll.core.Oval3RadiiGroove(usable_width=groove['A'], depth=groove['h'], r1=groove['r'], r2=groove['R1'], r3=groove['R'])
else:
shape = pyroll.core.FalseRoundGroove(depth=groove['h'], r1=0.0, r2=groove['R'])
return shape
h0 = 160e-3
billet_property = {
"temperature": 920 + 273.15,
"freiberg_flow_stress_coefficients": FreibergFlowStressCoefficients(
a=759.285 * 1e6,
m1=-0.00358,
m2=0.338339,
m3=-0.055943,
m4=0.000104,
m5=-0.000599,
m6=0,
m7=-0.448028,
m8=0.000198,
m9=0.356106,
baseStrain=0.1,
baseStrainRate=0.1),
"material": "Steel",
"density": 7.8e3,
"specific_heat_capacity": 6.9e2,
"thermal_conductivity": 23,
"strain": 0.0001,
}
in_profile = pyroll.core.Profile.box(
height=h0,
width=h0,
corner_radius=3e-3,
**billet_property
)
data = {
'groove': ['BOX1-1', 'BOX2-1', 'BOX3-1', 'BOX4-1', 'OVP5-1', 'R6-1'],
'A': [247.63, 175.56, 192.4, 130.0, 160.0, 108.32],
'a': [202.6, 151.12, 158.0, 107.87, 0, 0],
'h': [50.6, 54.0, 38.9, 46.0, 37.4, 44.0],
'R': [30.0, 31.0, 21.3, 23.2, 205.9, 49.0],
'R1': [0, 0, 0, 0, 30.2, 0],
'r': [15.1, 15.8, 10.8, 11.7, 8.00, 10.0],
'alpha': [24, 12.75, 23.61, 13.52, 30, 31],
}
index = ['BOX1-1', 'BOX2-1', 'BOX3-1', 'BOX4-1', 'OVP5-1', 'R6-1']
grooves = pd.DataFrame(data, index=index)
grooves.drop('groove', axis=1, inplace=True)
grooves = grooves/1e3
grooves['alpha'] = grooves['alpha']*1e3
groove = create_groove('OVP5-1', grooves)
data = {
'stand': [1, 2, 3, 4, 5, 6],
'groove': ['BOX1-1', 'BOX2-1', 'BOX3-1', 'BOX4-1', 'OVP5-1', 'R6-1'],
'e': [43, 37, 29, 25, 12, 10],
'r0': [0.375, 0.375, 0.325, 0.325, 0.325, 0.325],
'vl': [0.158, 0.202, 0.285, 0.373, 0.531, 0.698]
}
stands = pd.DataFrame(data)
stands['e'] = stands['e']/1e3
stand_positions = {1: np.float64(0.0),
2: np.float64(3.8),
3: np.float64(7.0),
4: np.float64(9.2),
5: np.float64(11.4),
6: np.float64(13.6),}
roll_passes = []
for i in range (len(stands)):
stand = stands.iloc[i]
stand_diameter = 2 * stand['r0']
groove = create_groove(stand['groove'], grooves)
roll_pass = pyroll.core.RollPass(
coulomb_friction_coefficient=0.3,
disk_element_count=20,
front_tension=0,
back_tension=0,
label=stand['groove'],
roll=pyroll.core.Roll(
groove=groove,
nominal_diameter=stand_diameter,
max_radius=stand['r0'],
min_radius = stand['r0'] - groove.depth,
poissons_ratio=0.3,
elastic_modulus=1e11,
rotational_frequency=stand['vl']/np.pi/stand_diameter,
),
# velocity=stand['vl'],
gap=stand['e'],
rotation=False,
)
if i == 0:
roll_pass.in_profile = in_profile
# roll_pass.orientation = 'h' if i%2 == 0 else 'v'
roll_passes.append(roll_pass)
if i + 1 < len(stands):
transport = pyroll.core.Transport(
label= f"{stand['stand']}:T",
duration=(stand_positions[stands.iloc[i + 1]['stand']] - stand_positions[stands.iloc[i]['stand']])/stand['vl'],
cooling_water_temperature = 273.15 + 20,
cooling_heat_transfer_coefficient=10,
convection_heat_transfer_coefficient=50, )
roll_passes.append(transport)
rotator = pyroll.core.Rotator(
# parent=roll_pass,
label=f"Rotator:{i}",
duration=0,
length=0,
)
roll_passes.append(rotator)
sequence = pyroll.core.PassSequence(roll_passes)
rps = [s for s in sequence if isinstance(s,pyroll.core.DeformationUnit)]
def passwise_solve(sequence, in_profile0, start=0):
for i in range(start, len(sequence)):
try:
if i > 0:
in_profile = sequence[i - 1].out_profile
else:
in_profile = in_profile0
print(f"try on pass {i}")
sequence[i].solve(in_profile=in_profile)
except Exception as e:
traceback.print_exc() # Prints the full traceback to stderr
# or, to get it as a string:
# print(traceback.format_exc())
print(f"solution faied at pass {i}")
return i
return i
sequence.solve(in_profile)
# start = 0
# start = passwise_solve(sequence, in_profile, start)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment