Last active
April 12, 2026 09:13
-
-
Save QiangF/667b8a26d7b6424b26889ed31b0512c3 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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