Skip to content
Open
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
3 changes: 2 additions & 1 deletion pyroll/neutral_point_estimator/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ class Config:
from . import sims_neutral_point_estimator
from . import equal_neutral_line_estimator
from . import lichansky_polyakov_ribbed_profile_neutral_point
from . import napatov_ribbed_profile_neutral_point
from . import napatov_ribbed_profile_neutral_point
from . import lippmann_mahrenholz
29 changes: 29 additions & 0 deletions pyroll/neutral_point_estimator/lippmann_mahrenholz.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import numpy as np

from . import Config
from .utils import chosen_estimator
from pyroll.core import SymmetricRollPass, Hook

SymmetricRollPass.Roll.relative_neutral_angle = Hook[float]()
"""Relative Neutral angle defined by Lippmann and Mahrenholz for the roll pass."""

@SymmetricRollPass.Roll.relative_neutral_angle
def relative_neutral_angle(self: SymmetricRollPass.Roll):
rp = self.roll_pass
mean_flow_stress = (rp.in_profile.flow_stress + 2 * rp.out_profile.flow_stress) / 3
abs_rel_draught = abs(rp.rel_draught)
back_tension_model_definition = -rp.back_tension
front_tension_model_definition = -rp.front_tension
relative_tension = (back_tension_model_definition - front_tension_model_definition) / mean_flow_stress

p1 = np.sqrt((1 - abs_rel_draught) / abs_rel_draught)
p2 = 1 / 2 * np.sqrt(rp.out_profile.equivalent_height / self.working_radius) * (relative_tension + np.log(1 - abs_rel_draught))
p3 = 1 / 2 * np.arctan(np.sqrt(abs_rel_draught / (1 - abs_rel_draught)))

return p1 * np.tan(p2 + p3)


@SymmetricRollPass.Roll.neutral_angle
def neutral_angle(self: SymmetricRollPass.Roll):
if chosen_estimator(Config.ESTIMATOR, "lippmann-mahrenholz"):
return self.entry_angle * self.relative_neutral_angle
89 changes: 89 additions & 0 deletions test/test_solve_lippmann_mahrenholz.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import logging
import webbrowser
from pathlib import Path

from pyroll.core import Profile, PassSequence, RollPass, Roll, CircularOvalGroove, Transport, RoundGroove, root_hooks


def test_solve_lippmann_mahrenholz(tmp_path: Path, caplog, monkeypatch):
caplog.set_level(logging.INFO, logger="pyroll")

import pyroll.neutral_point_estimator
monkeypatch.setenv("PYROLL_NEUTRAL_POINT_ESTIMATOR_ESTIMATOR", "LIPPMANN-MAHRENHOLZ")

root_hooks.add(Roll.neutral_point)

try:
in_profile = Profile.round(
diameter=30e-3,
temperature=1200 + 273.15,
strain=0,
material=["C45", "steel"],
flow_stress=100e6,
density=7.5e3,
thermal_capacity=690,
)

sequence = PassSequence([
RollPass(
label="Oval I",
roll=Roll(
groove=CircularOvalGroove(
depth=8e-3,
r1=6e-3,
r2=40e-3
),
nominal_radius=160e-3,
rotational_frequency=1
),
gap=2e-3,
coulomb_friction_coefficient=0.4,
back_tension=0,
front_tension=5e6
),
Transport(
label="I => II",
duration=1
),
RollPass(
label="Round II",
roll=Roll(
groove=RoundGroove(
r1=1e-3,
r2=12.5e-3,
depth=11.5e-3
),
nominal_radius=160e-3,
rotational_frequency=1
),
gap=2e-3,
coulomb_friction_coefficient=0.4,
back_tension=5e6,
front_tension=0
),
])

try:
sequence.solve(in_profile)

assert sequence[0].roll.neutral_point < 0
assert sequence[2].roll.neutral_point < 0

finally:
print("\nLog:")
print(caplog.text)
finally:
root_hooks.remove(Roll.neutral_point)

try:
import pyroll.report

report = pyroll.report.report(sequence)

report_file = tmp_path / "report.html"
report_file.write_text(report, encoding="utf-8")
print(report_file)
webbrowser.open(report_file.as_uri())

except ImportError:
pass
89 changes: 89 additions & 0 deletions test/test_solve_lippmann_mahrenholz3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import logging
import webbrowser
from pathlib import Path

from pyroll.core import Profile, Roll, ThreeRollPass, Transport, RoundGroove, CircularOvalGroove, PassSequence, root_hooks


def test_solve_lippmann_mahrenholz3(tmp_path: Path, caplog, monkeypatch):
caplog.set_level(logging.DEBUG, logger="pyroll")

import pyroll.neutral_point_estimator
monkeypatch.setenv("PYROLL_NEUTRAL_POINT_ESTIMATOR_ESTIMATOR", "LIPPMANN-MAHRENHOLZ")

root_hooks.add(Roll.neutral_point)

in_profile = Profile.round(
diameter=55e-3,
temperature=1200 + 273.15,
strain=0,
material=["C45", "steel"],
flow_stress=100e6,
density=7.5e3,
thermal_capacity=690,
)

sequence = PassSequence([
ThreeRollPass(
label="Oval I",
roll=Roll(
groove=CircularOvalGroove(
depth=8e-3,
r1=6e-3,
r2=40e-3,
pad_angle=30
),
nominal_radius=160e-3,
rotational_frequency=1
),
gap=2e-3,
coulomb_friction_coefficient=0.4,
back_tension=0,
front_tension=5e6
),
Transport(
label="I => II",
duration=1
),
ThreeRollPass(
label="Round II",
roll=Roll(
groove=RoundGroove(
r1=3e-3,
r2=25e-3,
depth=11e-3,
pad_angle=30
),
nominal_radius=160e-3,
rotational_frequency=1
),
gap=2e-3,
coulomb_friction_coefficient=0.4,
back_tension=5e6,
front_tension=0
),
])

try:
sequence.solve(in_profile)

assert sequence[0].roll.neutral_point < 0
assert sequence[2].roll.neutral_point < 0
finally:
root_hooks.remove(Roll.neutral_point)

print("\nLog:")
print(caplog.text)

try:
import pyroll.report

report = pyroll.report.report(sequence)

report_file = tmp_path / "report.html"
report_file.write_text(report, encoding="utf-8")
print(report_file)
webbrowser.open(report_file.as_uri())

except ImportError:
pass