Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
2a97d9f
Introduce draft of NotchApproxBinner
johannes-mueller Dec 11, 2024
7ccf6ca
Adjust Rainflow HCM to NotchApproxBinner
johannes-mueller Dec 11, 2024
026cf35
Apply NotchApproxBinner to Seeger Beste
johannes-mueller Dec 12, 2024
ad4131b
Adjust other modules to NotchApproxBinner
johannes-mueller Dec 12, 2024
eabdbe0
Adjust HCM rainflow counting unit tests to NotchApproxBinner
johannes-mueller Dec 12, 2024
a5e22bb
Add docstrings to NotchApproxBinner
johannes-mueller Dec 13, 2024
4c648a0
Drop Binned class for notch approximation and adjust tests accordingly
johannes-mueller Dec 13, 2024
7eb2d95
Drop assertions that checked for the LUTs of former Binned
johannes-mueller Dec 13, 2024
2c8ee98
Add tests for secondary branch notch approximation
johannes-mueller Dec 13, 2024
737102f
Drop `load` argument of notch approximation strain methods
johannes-mueller Dec 13, 2024
dd6c18f
Let FKMNonLinearDetector initialize NotchApproxBinner
johannes-mueller Dec 13, 2024
bd04e54
Use automatic binning of FKMNonLinearDetector
johannes-mueller Dec 13, 2024
fc08bc0
Adjust jupyter notebook
johannes-mueller Dec 16, 2024
8983ff3
Don't regenerate the test signal while collecting benchmark tests
johannes-mueller Dec 16, 2024
8bd8763
Add docstrings for .primary() and .secondary()
johannes-mueller Dec 16, 2024
bd97d96
Add abstract base class methods to NotchApproximationLawBase
johannes-mueller Dec 17, 2024
fff5b23
Drop obsolete file
johannes-mueller Dec 17, 2024
a7105fd
Simplifications
johannes-mueller Jan 13, 2025
02dadf3
Handle an edge case in recording epslilon LF on open hysteresis
johannes-mueller Jan 16, 2025
0e7c15e
Cleanups in tests
johannes-mueller Jan 29, 2025
1867584
Improvements from review and some refactorings
johannes-mueller Feb 5, 2025
435217f
Drop maximum_absolute_load parameter for FKM NK rainflow counter
johannes-mueller Feb 6, 2025
b8e7006
Handle case when first mesh load point is zero
johannes-mueller Feb 6, 2025
b136190
Add a couple of docstrings to abstract methods
johannes-mueller Feb 6, 2025
a3d7452
Restore notch approximation law object in result output
johannes-mueller Feb 6, 2025
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
11 changes: 6 additions & 5 deletions src/pylife/materiallaws/notch_approximation_law_seegerbeste.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def stress(self, load, *, rtol=1e-4, tol=1e-4):
The resulting stress
'''
# initial value as given by correction document to FKM nonlinear
x0 = load * (1 - (1 - 1/self._K_p)/1000)
x0 = np.asarray(load * (1 - (1 - 1/self._K_p)/1000))

# suppress the divergence warnings
with warnings.catch_warnings():
Expand All @@ -96,7 +96,8 @@ def stress(self, load, *, rtol=1e-4, tol=1e-4):
# or (value, converged, zero_der) for vector-valued invocation

# only for multiple points at once, if some points diverged
if len(stress) == 3 and not stress[1].all():
multidim = len(x0.shape) > 1 and x0.shape[1] > 1
if multidim and not stress[1].all():
stress = self._stress_fix_not_converged_values(stress, load, x0, rtol, tol)

return stress[0]
Expand Down Expand Up @@ -461,7 +462,7 @@ def _stress_fix_not_converged_values(self, stress, load, x0, rtol, tol):
'''For the values that did not converge in the previous vectorized call to optimize.newton,
call optimize.newton again on the scalar value. This usually finds the correct solution.'''

indices_diverged = [index for index, is_converged in enumerate(stress[1]) if not is_converged]
indices_diverged = np.where(~stress[1].all(axis=1))[0]
x0_array = np.asarray(x0)
load_array = np.asarray(load)

Expand All @@ -471,13 +472,13 @@ def _stress_fix_not_converged_values(self, stress, load, x0, rtol, tol):
load_diverged = load_array[index_diverged]
result = optimize.newton(
func=self._stress_implicit,
x0=x0_diverged,
x0=np.asarray(x0_diverged),
args=([load_diverged]),
full_output=True,
rtol=rtol, tol=tol, maxiter=50
)

if result[1].converged:
if result.converged.all():
stress[0][index_diverged] = result[0]
return stress

Expand Down
24 changes: 7 additions & 17 deletions src/pylife/strength/fkm_nonlinear/assessment_nonlinear_standard.py
Original file line number Diff line number Diff line change
Expand Up @@ -389,27 +389,21 @@ def _compute_component_woehler_curves(assessment_parameters):
return assessment_parameters, component_woehler_curve_P_RAM, component_woehler_curve_P_RAJ


def _compute_hcm_RAM(assessment_parameters, scaled_load_sequence, maximum_absolute_load):
def _compute_hcm_RAM(assessment_parameters, scaled_load_sequence, maximum_absolute_):
"""Perform the HCM rainflow counting with the extended Neuber notch approximation.
The HCM algorithm is executed twice, as described in the FKM nonlinear guideline."""

# initialize notch approximation law
E, K_prime, n_prime, K_p = assessment_parameters[["E", "K_prime", "n_prime", "K_p"]]
extended_neuber = pylife.materiallaws.notch_approximation_law.ExtendedNeuber(E, K_prime, n_prime, K_p)

# wrap the notch approximation law by a binning class, which precomputes the values
extended_neuber_binned = (
pylife.materiallaws.notch_approximation_law.NotchApproxBinner(
extended_neuber
).initialize(maximum_absolute_load)
)

# create recorder object
recorder = pylife.stress.rainflow.recorders.FKMNonlinearRecorder()

# create detector object
detector = pylife.stress.rainflow.fkm_nonlinear.FKMNonlinearDetector(
recorder=recorder, notch_approximation_law=extended_neuber_binned, binner=None)
recorder=recorder, notch_approximation_law=extended_neuber
)

# perform HCM algorithm, first run
detector.process_hcm_first(scaled_load_sequence)
Expand All @@ -418,7 +412,7 @@ def _compute_hcm_RAM(assessment_parameters, scaled_load_sequence, maximum_absolu
# perform HCM algorithm, second run
detector.process_hcm_second(scaled_load_sequence)

return detector_1st, detector, extended_neuber_binned, recorder
return detector_1st, detector, extended_neuber, recorder


def _compute_damage_and_lifetimes_RAM(assessment_parameters, recorder, component_woehler_curve_P_RAM, result):
Expand Down Expand Up @@ -493,17 +487,13 @@ def _compute_hcm_RAJ(assessment_parameters, scaled_load_sequence, maximum_absolu
E, K_prime, n_prime, K_p = assessment_parameters[["E", "K_prime", "n_prime", "K_p"]]
seeger_beste = pylife.materiallaws.notch_approximation_law_seegerbeste.SeegerBeste(E, K_prime, n_prime, K_p)

# wrap the notch approximation law by a binning class, which precomputes the values
seeger_beste_binned = pylife.materiallaws.notch_approximation_law.NotchApproxBinner(
seeger_beste
).initialize(maximum_absolute_load)

# create recorder object
recorder = pylife.stress.rainflow.recorders.FKMNonlinearRecorder()

# create detector object
detector = pylife.stress.rainflow.fkm_nonlinear.FKMNonlinearDetector(
recorder=recorder, notch_approximation_law=seeger_beste_binned, binner=None)
recorder=recorder, notch_approximation_law=seeger_beste
)
detector_1st = copy.deepcopy(detector)

# perform HCM algorithm, first run
Expand All @@ -512,7 +502,7 @@ def _compute_hcm_RAJ(assessment_parameters, scaled_load_sequence, maximum_absolu
# perform HCM algorithm, second run
detector.process_hcm_second(scaled_load_sequence)

return detector_1st, detector, seeger_beste_binned, recorder
return detector_1st, detector, seeger_beste, recorder


def _compute_damage_and_lifetimes_RAJ(assessment_parameters, recorder, component_woehler_curve_P_RAJ, result):
Expand Down
37 changes: 4 additions & 33 deletions tests/strength/test_damage_calculator.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,20 +92,12 @@ def test_woehler_curve_P_RAM_collective_has_no_index():

load_sequence_list = pd.Series([143.696, -287.392, 143.696, -359.240, 287.392, 0.000, 287.392, -287.392])

# wrap the notch approximation law by a binning class, which precomputes the values
maximum_absolute_load = max(np.abs(load_sequence_list))
extended_neuber_binned = (
pylife.materiallaws.notch_approximation_law.NotchApproxBinner(
extended_neuber
).initialize(maximum_absolute_load)
)

# create recorder object
recorder = pylife.stress.rainflow.recorders.FKMNonlinearRecorder()

# create detector object
detector = pylife.stress.rainflow.fkm_nonlinear.FKMNonlinearDetector(
recorder=recorder, notch_approximation_law=extended_neuber_binned, binner=None
recorder=recorder, notch_approximation_law=extended_neuber
)

# perform HCM algorithm, first run
Expand Down Expand Up @@ -202,20 +194,12 @@ def test_woehler_curve_P_RAM_collective_has_MultiIndex():

load_sequence_list = pd.Series([143.696, -287.392, 143.696, -359.240, 287.392, 0.000, 287.392, -287.392])

# wrap the notch approximation law by a binning class, which precomputes the values
maximum_absolute_load = max(np.abs(load_sequence_list))
extended_neuber_binned = (
pylife.materiallaws.notch_approximation_law.NotchApproxBinner(
extended_neuber
).initialize(maximum_absolute_load)
)

# create recorder object
recorder = pylife.stress.rainflow.recorders.FKMNonlinearRecorder()

# create detector object
detector = pylife.stress.rainflow.fkm_nonlinear.FKMNonlinearDetector(
recorder=recorder, notch_approximation_law=extended_neuber_binned, binner=None
recorder=recorder, notch_approximation_law=extended_neuber
)

# perform HCM algorithm, first run
Expand Down Expand Up @@ -300,19 +284,12 @@ def test_woehler_curve_P_RAJ_has_no_index():
seeger_beste = pylife.materiallaws.notch_approximation_law_seegerbeste.SeegerBeste(E, K_prime, n_prime, K_p)

load_sequence_list = pd.Series([143.696, -287.392, 143.696, -359.240, 287.392, 0.000, 287.392, -287.392])

# wrap the notch approximation law by a binning class, which precomputes the values
maximum_absolute_load = max(np.abs(load_sequence_list))
seeger_beste_binned = pylife.materiallaws.notch_approximation_law.NotchApproxBinner(
seeger_beste
).initialize(maximum_absolute_load)

# create recorder object
recorder = pylife.stress.rainflow.recorders.FKMNonlinearRecorder()

# create detector object
detector = pylife.stress.rainflow.fkm_nonlinear.FKMNonlinearDetector(
recorder=recorder, notch_approximation_law=seeger_beste_binned, binner=None
recorder=recorder, notch_approximation_law=seeger_beste
)

# perform HCM algorithm, first run
Expand Down Expand Up @@ -410,18 +387,12 @@ def test_woehler_curve_P_RAJ_has_MultiIndex():

load_sequence_list = pd.Series([143.696, -287.392, 143.696, -359.240, 287.392, 0.000, 287.392, -287.392])

# wrap the notch approximation law by a binning class, which precomputes the values
maximum_absolute_load = max(np.abs(load_sequence_list))
seeger_beste_binned = pylife.materiallaws.notch_approximation_law.NotchApproxBinner(
seeger_beste
).initialize(maximum_absolute_load)

# create recorder object
recorder = pylife.stress.rainflow.recorders.FKMNonlinearRecorder()

# create detector object
detector = pylife.stress.rainflow.fkm_nonlinear.FKMNonlinearDetector(
recorder=recorder, notch_approximation_law=seeger_beste_binned, binner=None
recorder=recorder, notch_approximation_law=seeger_beste
)

# perform HCM algorithm, first run
Expand Down