From bbe8926f431f7961a61a90a7d9a1e8a9cccbff38 Mon Sep 17 00:00:00 2001 From: tovop Date: Mon, 21 Jun 2021 11:22:15 +0200 Subject: [PATCH 1/3] New generic S-N model for mean load and corrosion dependent fatigue capacity. Tests and examples are updated. --- docs/source/examples/mooring_fatigue.py | 12 +- qats/fatigue/sn.py | 686 +++++++++++------------- test/test_fatigue_sn.py | 91 ++-- 3 files changed, 371 insertions(+), 418 deletions(-) diff --git a/docs/source/examples/mooring_fatigue.py b/docs/source/examples/mooring_fatigue.py index 011ff19b..08198a71 100644 --- a/docs/source/examples/mooring_fatigue.py +++ b/docs/source/examples/mooring_fatigue.py @@ -2,15 +2,17 @@ Calculate mooring line fatigue. """ import os +import numpy as np from math import pi from qats import TsDB -from qats.fatigue.sn import SNCurve, minersum +from qats.fatigue.sn import SNCurve + # load time series db = TsDB.fromfile(os.path.join("..", "..", "..", "data", "simo_p_out.ts")) # initiate SN-curve: DNVGL-OS-E301 curve for studless chain -sncurve = SNCurve(name="Studless chain OS-E301", m1=3.0, a1=6e10) +sncurve = SNCurve(name="Studless chain OS-E301", m=3.0, b0=10.778) # Calculate fatigue damage for all mooring line tension time series (kN) for ts in db.getl(names='tension_*_qs'): @@ -21,11 +23,11 @@ ranges, _, counts = cycles.T # calculate cross section stress cycles (shown here: 118mm studless chain, with unit [kN] for tension cycles) - area = 2. * pi * (118. / 2.) ** 2. # mm^2 - ranges = [r * 1e3 / area for r in ranges] # MPa + area = 2. * pi * (118. / 2.) ** 2. # mm^2 + ranges = np.array([r * 1e3 / area for r in ranges]) # MPa # calculate fatigue damage from Palmgren-Miner rule (SCF=1, no thickness correction) - damage = minersum(ranges, counts, sncurve) + damage, _ = sncurve.minersum(ranges, counts) # print summary print(f"{ts.name}:") diff --git a/qats/fatigue/sn.py b/qats/fatigue/sn.py index 8c5c1187..2f67e16f 100644 --- a/qats/fatigue/sn.py +++ b/qats/fatigue/sn.py @@ -1,478 +1,422 @@ #!/usr/bin/env python # coding: utf-8 """ -Classes and functions for fatigue calculations: - - SNCurve (class) - - Fatigue damage calculation (functions) +Classes and functions for fatigue capacity and fatigue damage calculations """ import numpy as np from scipy.special import gamma as gammafunc, gammainc, gammaincc - -# todo: Update SNCurve docstring to include description of class and attributes +from typing import Optional, Tuple, Union class SNCurve(object): """ - S-N curve representing fatigue capacity versus cyclic stresses. - - Parameters - ---------- - name : str - S-N curve name - m1 : float - Negative inverse slope parameter (for bilinear curves: used for N < `nswitch`). - m2 : float, optional - Negative inverse slope parameter for N > `nswitch` - a1 : float, optional - Intercept parameter for N <= `nswitch`. - loga1 : float, optional - Log10 of a1. Must be given if `a1` is not specified. - nswitch : float, optional - Number of cycles at transition from `m1` to `m2`. Required if `m2` is specified. - t_exp : float, optional - Thickness correction exponent. If not specified, thickness may not be specified in later calculations. - t_ref : float, optional - Reference thickness [mm]. If not specified, thickness may not be specified in later calculations. + S-N data model Attributes ---------- - a1 : float - Intercept parameter for N <= `nswitch`. - a2 : float - Intercept parameter for N > `nswitch`. Equals `a1` for linear curves. - loga1 : float - Common logarithm with base 10 of `a1`. - loga2 : float - Common logarithm with base 10 of `a2`. - m1 : float - Negative inverse slope parameter (for bilinear curves: used for N < `nswitch`). - m2 : float - Negative inverse slope parameter for N > `nswitch`. Equals `m1` for linear curves. - name : str - S-N curve name. - nswitch : float - Number of cycles at transition from `m1` to `m2`. Applies only to bilinear curves. - sswitch : float - Stress range at transition from `m1` to `m2`. Applies only to bilinear curves. - t_exp : float - Thickness correction exponent. - t_ref : float, optional - Reference thickness [mm] for thickness correction. + m : float + Slope of first leg of the curve + b0: float + Constant coefficient in equation to calculate the intercept parameter + name : Optional[str] + Name/identifier + description : Optional[str] + Description of the curve + unit: Optional[str] + Unit of measure for the stress ranges e.g. MPa + b1: Optional[float] + Mean stress coefficient in equation to calculate the intercept parameter + b2: Optional[float] + Corrosion grade coefficient in equation to calculate the intercept parameter + default_g1: Optional[float] + Default value of g1(s_m) function, where s_m is the mean load + default_g2: Optional[float] + Default value of g2(c) function, where c is the corrosion grade + m2: Optional[float] + Slope of second leg of the curve, applies only to bi-linear curves + n_switch: Optional[float] + Point (in terms of number of cycles to failure) where the slope changes, applies only to bi-linear curves + fatigue_limit: Optional[float] + Fatigue limit in terms of stress range + t_ref: Optional[float] + Reference thickness for thickness correction + t_exp: Optional[float] + Exponent for thickness correction Notes ----- - For linear curves (single slope), the following input parameters are required: m1, a1 (or loga1). - For bi-linear curves, the following additional parameters are required: m2, nswitch. + The dependency to mean load and corrosion is included by expressing the intercept parameter as a + function of these parameters: - If S-N curve is overdefined (e.g. both loga1 and a1 are defined), the S-N curve is established based on the - parameter order listed above (under "Parameters"). - """ + logA(s_m, c) = b0 + b1 * g1(s_m) + b2 * g2(c) + + where b0, b1 and b2 are constant coefficients and g1 and g2 are functions of mean load (s_m) and + corrosion grade (c) respectively. These functions are generally nonlinear. + + References + ---------- + 1. Lone et.al. (2021), Fatigue assessment of mooring chain considering the effects of mean load and corrosion, + OMAE2021-62775 - def __init__(self, name, m1, **kwargs): + """ + def __init__(self, m: float, b0: float, name: str = None, description: str = None, unit: str = None, + b1: float = None, b2: float = None, default_g1: float = None, default_g2: float = None, + m2: float = None, n_switch: float = None, fatigue_limit: float = None, t_ref: float = None, + t_exp: float = None): self.name = name + self.description = description + self.unit = unit + self.m = m + self.b0 = b0 + self.b1 = b1 + self.b2 = b2 + self.default_g1 = default_g1 + self.default_g2 = default_g2 + self.m2 = m2 + self.n_switch = n_switch + self.fatigue_limit = fatigue_limit + self.t_ref = t_ref + self.t_exp = t_exp + + def is_bilinear(self) -> bool: + """Is it a bi-linear curve.""" + return self.m2 is not None and self.n_switch is not None + + def is_mean_load_and_corrosion_grade_dependent(self) -> bool: + """Is it a curve which depends on mean load and corrosion grade.""" + return self.b1 is not None and self.b2 is not None and \ + self.default_g1 is not None and self.default_g2 is not None + + def loga(self, g1: Union[float, np.ndarray] = None, g2: Union[float, np.ndarray] = None) -> Union[float, np.ndarray]: + """ + Logarithm of intercept parameter + + Parameters + ---------- + g1 : float or np.ndarray, optional + value of g1(s_m), where s_m is the mean load + g2 : float or np.ndarray, optional + value of g1(c), where c is the corrosion grade + + Returns + ------- + float or np.ndarray + Logarithm of intercept parameter + + Notes + ----- + The specified mean load (g1) and corrosion grade (g2) must be consistent with the parameter + definitions applied with the actual S-N curve. + + For curves that are mean load and corrosion grade dependent, the curves + reference values are applied by default if not provided. + """ + if self.is_mean_load_and_corrosion_grade_dependent(): + if g1 is None: + g1 = self.default_g1 + + if g2 is None: + g2 = self.default_g2 + + return self.b0 + self.b1 * g1 + self.b2 * g2 - self.m1 = m1 - self.m2 = m2 = kwargs.get("m2", None) - - self.t_exp = t_exp = kwargs.get("t_exp", None) - self.t_ref = t_ref = kwargs.get("t_ref", None) - - # check parameters - if m1 is None: - raise ValueError("parameter `m1` must be given") - - if t_exp is None and t_ref is None: - # thickness correction not specified - pass - elif t_exp is None or t_ref is None: - raise ValueError("if thickness correction is specified, both parameters `t_exp` and `t_ref` " - "must be specified") - - # check and deduct intercept parameter(s), etc. - a1 = kwargs.get("a1", None) - loga1 = kwargs.get("loga1", None) - if a1 is not None: - loga1 = np.log10(a1) - elif loga1 is not None: - a1 = 10 ** loga1 - else: - raise ValueError("either `a1` or `loga1` must be specified") - - # handle bi-linear curves ( - if self.bilinear is True: - nswitch = kwargs.get("nswitch", None) - if nswitch is None: - raise ValueError("`nswitch` must be specified for bi-linear curves") - loga2 = m2 / m1 * loga1 + (1 - m2/m1) * np.log10(nswitch) - a2 = 10 ** loga2 - sswitch = 10 ** ((loga1 - np.log10(nswitch)) / m1) else: - a2 = None - loga2 = None - nswitch = None - sswitch = None - - # store all parameters - self.a1 = a1 - self.a2 = a2 - self.loga1 = loga1 - self.loga2 = loga2 - self.nswitch = nswitch - self.sswitch = sswitch - - def __repr__(self): - str_type = "bi-linear" if self.bilinear is True else "linear" - return '' % (self.name, str_type) - - @property - def a(self): + return self.b0 + + def a(self, g1: Union[float, np.ndarray] = None, g2: Union[float, np.ndarray] = None) -> Union[float, np.ndarray]: """ - Intercept parameter of linear (single slope) S-N curve (equal to `a1`). - For bi-linear curves, use `a1` and `a2` instead. + Intercept parameter + + Parameters + ---------- + g1 : float or np.ndarray, optional + value of g1(s_m), where s_m is the mean load + g2 : float or np.ndarray, optional + value of g1(c), where c is the corrosion grade + + Returns + ------- + float or np.ndarray + Intercept parameter + + Notes + ----- + The specified mean load (g1) and corrosion grade (g2) must be consistent with the parameter + definitions applied with the actual S-N curve. + + For curves that are mean load and corrosion grade dependent, the curves + reference values are applied by default if not provided. """ - # should only be available for linear S-N curves - otherwise, a1 and a2 should be used! - assert self.a2 is None, "For bi-linear curves, use `a1` and `a2` instead of `a`" - return self.a1 + return 10. ** self.loga(g1=g1, g2=g2) - @property - def bilinear(self): + def loga2(self) -> float: """ - Returns True if S-N curve is bi-linear, otherwise False. + Logarithm of intercept parameter for the second leg. + + Applies only to bi-linear curves. """ - if self.m2 is None: - return False - else: - return True + assert self.is_bilinear(), "The second intercept parameter applies only to bi-linear S-N curves. " \ + "Make sure that both `m2` and `n_switch` are specified." + return self.m2 / self.m * self.loga() + (1 - self.m2/self.m) * np.log10(self.n_switch) - @property - def loga(self): + def a2(self) -> float: """ - Logarithm (base 10) of intercept parameter of linear (single slope) S-N curve (equal to `loga1`). - For bi-linear curves, use `loga1` and `loga2` instead. + Intercept parameter for the second leg. + + Applies only to bi-linear curves. """ - # should only be available for linear S-N curves - otherwise, a1 and a2 should be used! - assert self.loga2 is None, "For bi-linear curves, use `loga1` and `loga2` instead of `loga`" - return self.loga1 + return 10. ** self.loga2() + + def s_switch(self) -> float: + """The stress range where the slope changes, applies only to bi-linear curves""" + assert self.is_bilinear(), "The second intercept parameter applies only to bi-linear S-N curves. " \ + "Make sure that both `m2` and `n_switch` are specified." + return 10 ** ((self.loga() - np.log10(self.n_switch)) / self.m) - @property - def m(self): + def thickness_correction(self, t: float) -> float: """ - Slope parameter of linear (single slope) S-N curve (equal to `m1`). - Not available for bi-linear curves. + Thickness correction for specified thickness. + + Parameters + ---------- + t : float + Thickness [mm] + Returns + ------- + float + Thickness correction factor. + + Raises + ------ + ValueError + If thickness correction is not defined, i.e. `t_exp` and `t_ref` are not defined. """ - # should only be available for linear S-N curves - otherwise, m1 and m2 should be used! - assert self.m2 is None, "For bi-linear curves, use `m1` and `m2` instead of `m`" - return self.m1 + assert self.t_ref is not None and self.t_exp is not None, "Thickness correction parameters " \ + "`t_ref` and `t_exp` are not defined." - def fatigue_strength(self, n, t=None): + if t < self.t_ref: # t = tref is used for thickness less than tref, ref. DNV-RP-C203 eq. 2.4.3 + t = self.t_ref + + return (t / self.t_ref) ** self.t_exp + + def strength(self, n: Union[float, np.ndarray], g1: Union[float, np.ndarray] = None, + g2: Union[float, np.ndarray] = None, t: float = None) -> Union[float, np.ndarray]: """ Magnitude of stress range leading to a particular fatigue life (in terms of number of cycles. Parameters ---------- - n : float + n : float or numpy.ndarray Number of cycles (fatigue life) [-]. + g1 : float or numpy.ndarray, optional + value of g1(s_m), where s_m is the mean load + g2 : float or numpy.ndarray, optional + value of g1(c), where c is the corrosion grade t : float, optional Thickness [mm]. If specified, thickness reference and exponent must be defined for the S-N curve. If not specified, thickness correction is not taken into account. Returns ------- - float - Fatigue strength, i.e. magnitude of stress range leading to specified fatigue life (no. of cycles). + float or numpy.ndarray + Magnitude of stress range leading to specified fatigue life (no. of cycles). + + Notes + ----- + The specified mean load (g1) and corrosion grade (g2) must be consistent with the parameter + definitions applied with the actual S-N curve. + + For curves that are mean load and corrosion grade dependent, the curves + reference values are applied by default if not provided. - Raises - ------ - ValueError: If thickness is specified, but thickness reference and exponent is not defined. """ + # TODO: Handle cases where a fatigue limit is specified, np.nan for n > onset of the fatigue limit? + n = np.asarray(n) + g1 = np.asarray(g1) + g2 = np.asarray(g2) + # thickness correction if t is not None: - # thickness correction term - try: - tcorr = self.thickness_correction(t) - except ValueError: - raise + t_correction = self.thickness_correction(t) else: - # todo: consider to raise error if t_exp and t_ref is specified, but t not given (unless suppressed) - # no thickness correction term implies tk=1.0 - tcorr = 1.0 + t_correction = 1.0 # S-N parameters for specified stress range - if self.bilinear is False or n <= self.nswitch: - m = self.m1 - loga = self.loga1 + if not self.is_bilinear() or n <= self.n_switch: + m = self.m + loga = self.loga(g1=g1, g2=g2) else: m = self.m2 - loga = self.loga2 + loga = self.loga2() # fatigue strength, ref. DNV-RP-C203 (2016) eq. 2.4.3 - s = 1 / tcorr * 10 ** ((loga - np.log10(n)) / m) + s = 1. / t_correction * 10 ** ((loga - np.log10(n)) / m) - return s + # return float if input `n` was a float + if s.ndim == 0: + # float + return s.item() + else: + return s - def n(self, s, t=None): + def n(self, s: Union[float, np.ndarray], g1: Union[float, np.ndarray] = None, g2: Union[float, np.ndarray] = None, + t: float = None) -> Union[float, np.ndarray]: """ - Predicted number of cycles to failure for specified stress range(s) and thickness. + Predicted number of cycles to failure for specified stress range(s). Parameters ---------- - s : float or np.ndarray - Stress range(s) [MPa]. + s : float or numpy.ndarray + Stress range(s). + g1 : float or numpy.ndarray, optional + value of g1(s_m), where s_m is the mean load + g2 : float or numpy.ndarray, optional + value of g1(c), where c is the corrosion grade t : float, optional Thickness [mm]. If specified, thickness reference and exponent must be defined for the S-N curve. If not specified, thickness correction is not taken into account. Returns ------- - float or np.ndarray + float or numpy.ndarray Predicted number of cycles to failure. Output type is same as input type (float or np.ndarray) - Raises - ------ - ValueError: If thickness is specified, but thickness reference and exponent is not defined. """ + # TODO: Handle cases where a fatigue limit is specified, np.inf for s < fatigue limit? s = np.asarray(s) + g1 = np.asarray(g1) + g2 = np.asarray(g2) # thickness correction if t is not None: - # thickness correction term - try: - tcorr = self.thickness_correction(t) - except ValueError: - raise + t_correction = self.thickness_correction(t) else: - # todo: consider to raise error if t_exp and t_ref is specified, but t not given (unless suppressed) - # no thickness correction term implies tk=1.0 - tcorr = 1.0 + t_correction = 1.0 - # calculate fatigue limit `n`, ref. DNV-RP-C203 (2016) eq. 2.4.3 + # calculate number of cycles to failure `n`, ref. DNV-RP-C203 (2016) eq. 2.4.3 # ... using appropriate S-N parameters for specified stress range(s) - if self.bilinear is False: + if not self.is_bilinear(): # single slope sn curve - n = 10 ** (self.loga1 - self.m1 * np.log10(s * tcorr)) - return n + return 10 ** (self.loga(g1=g1, g2=g2) - self.m * np.log10(s * t_correction)) else: # bi-linear curve n = np.zeros(s.shape) - ind = s >= self.sswitch + + # find stress ranges above the point where the slope changes + ind = s >= self.s_switch() # fatigue limits for upper part of curve - n[ind] = 10 ** (self.loga1 - self.m1 * np.log10(s[ind] * tcorr)) + n[ind] = 10 ** (self.loga(g1=g1, g2=g2) - self.m * np.log10(s[ind] * t_correction)) + # fatigue limits for lower part of curve - n[~ind] = 10 ** (self.loga2 - self.m2 * np.log10(s[~ind] * tcorr)) + n[~ind] = 10 ** (self.loga2() - self.m2 * np.log10(s[~ind] * t_correction)) + + # return float if input `s` was a float if n.ndim == 0: # float return n.item() else: return n - def thickness_correction(self, t): + def minersum(self, ranges: np.ndarray, count: np.ndarray, g1: Union[float, np.ndarray] = None, + g2: Union[float, np.ndarray] = None, df: float = 1., scf: float = 1., th: float = None + ) -> Tuple[float, np.ndarray]: """ - Thickness correction for specified thickness. + Fatigue damage calculation (Miner-Palmgren sum) based on stress cycle histogram Parameters ---------- - t : float - Thickness [mm] + ranges : np.ndarray + Stress cycle ranges + count : np.ndarray + Stress cycle counts + g1 : float or numpy.ndarray, optional + value of g1(s_m), where s_m is the mean load + g2 : float or numpy.ndarray, optional + value of g1(c), where c is the corrosion grade + df: float, optional + Factor scaling reference duration. Can be used to scale the histogram from cycle rate to number of cycles or + to scale from one reference duration say. 100 seconds to a different reference duration say 10800 seconds. + Use 1 (the default) if histogram already represents number of cycles during the same period of time. + scf: float, optional + Stress concentration factor to be applied on stress ranges. Default: 1. + th: float, optional + Thickness [mm] for thickness correction. If specified, reference thickness and thickness exponent must be + defined for the S-N curve given. Returns ------- float - Thickness correction factor. + Total fatigue damage (Palmgren-Miner sum). + np.ndarray + Fatigue damage (Palmgren-Miner sum) per bin in the cycle distribution + """ + # calculate fatigue damage per bin (combination of range and count) of the cycle distribution + # apply mean load and corrosion grade dependency if relevant (kwargs) + # scale stresses with stress concentration factor + # scale to the correct reference duration + # apply thickness correction if any + damage_per_bin = df * count / self.n(s=ranges * scf, g1=g1, g2=g2, t=th) + return float(np.sum(damage_per_bin)), damage_per_bin + + def minersum_weibull(self, q: float, h: float, v0: float, duration: float = 31556952., scf: float = 1., + th: float = None): + """ + Fatigue damage (Palmgren-Miner sum) calculation based on (2-parameter) Weibull stress cycle distribution and + S-N curve. Ref. DNV-RP-C03 (2016) eq. F.12-1. + + Parameters + ---------- + q: float + Weibull scale parameter (in 2-parameter distribution). + h: float + Weibull shape parameter (in 2-parameter distribution). + v0: float, + Cycle rate [1/s]. + duration: float, optional + Duration [s] (or design life, in seconds). Default is 31536000 (no. of seconds in a year, or 365 days). + scf: float, optional + Stress concentration factor to be applied on stress ranges. + th: float, optional + Thickness [mm] for thickness correction. If specified, reference thickness and thickness exponent must be + defined for the S-N curve given. + + Returns + ------- + float + Fatigue damage (Palmgren-Miner sum). + Raises ------ - ValueError - If thickness correction is not defined, i.e. `t_exp` and `t_ref` are not defined. + ValueError: + If thickness is given but thickness correction not specified for S-N curve. """ - try: - if t < self.t_ref: # t = tref is used for thickness less than tref, ref. DNV-RP-C203 eq. 2.4.3 - t = self.t_ref - tcorr = (t / self.t_ref) ** self.t_exp - except TypeError: - raise ValueError("thickness correction is not defined, i.e. `t_exp` and `t_ref` are not specified") - return tcorr - - def print_parameters(self): - s = "%(name)s\n" \ - "----------------------------------\n" \ - "m1 : %(m1).1f\n" \ - "a1 : %(a1).2e\n" \ - "log(a1) : %(loga1).3f\n" % self.__dict__ - if self.bilinear is True: - s += "nswitch : %(nswitch).1e\n" \ - "m2 : %(m2).1f\n" \ - "a2 : %(a2).2e\n" \ - "log(a2) : %(loga2).3f\n" \ - "sswitch : %(sswitch).3f\n" % self.__dict__ - - s += "t_exp : %(t_exp)s\n" \ - "t_ref : %(t_ref)s\n" % self.__dict__ - - print(s) - return - - -def minersum(srange, count, sn, td=1., scf=1., th=None, retbins=False, args=(), kwds=None): - """ - Fatigue damage (Palmgren-Miner sum) calculation based on stress cycle histogram and S-N curve. + def cigf(a, x): + """ Complementary incomplete gamma function """ + return gammaincc(a, x) * gammafunc(a) - Parameters - ---------- - srange: np.ndarray or list of floats - List of stress ranges in histogram (Note: only one value per bin). - count: np.ndarray or list of floats - Cycle count for each of the stress ranges. May be specified as number of cycles [-] or cycle rate [1/s]. - If cycle rate is specified, specify duration `td` for scaling to number of cycles. - sn: dict or object or callable - Dictionary with S-N curve parameters, or class instance, or callable (function). - If **dict**: An :class:`SNCurve` instance is initiated based on parameters defined in dict. Expected keys are - 'm1' and 'a1' (or 'loga1') for linear S-N curve, and also 'm2' and 'nswitch' if bi-linear S-N curve. - If **object**: Assumed to be class instance, and expected to have a callable method `n` which takes stress range - array as input (e.g. an instance of the :class:`SNCurve` class.). - If **callable**: A function with takes stress range array as input, and returns an array of fatigue capacity - (no. of cycles to failure), similar to :meth:`SNCurve.n`. Additional positional and keyword arguments may be - passed using parameter `args` and `kwargs`. - td: float, optional - Duration [s]. Used to scale the histogram from cycle rate to number of cycles. - Use 1 (the default) if histogram already represents number of cycles. - scf: float, optional - Stress concentration factor to be applied on stress ranges. Default: 1. - th: float, optional - Thickness [mm] for thickness correction. If specified, reference thickness and thickness exponent must be - defined for the S-N curve given. NOTE: This parameter is only accepted if parameter `sn` is given as a `dict` - or a :class:`SNCurve` instance. In any other case, used the `args` or `kwds` parameter to pass additional - parameters to the capacity function. - retbins: bool, optional - If True, minersum per bin is also returned. - args : tuple, optional - Tuple of arguments that are passed to the capacity function defined by parameter `sn`. - kwds : dict, optional - Dictionary with keyword arguments that are passed to the capacity function defined by parameter `sn`. - - Returns - ------- - float - Fatigue damage (Palmgren-Miner sum). - np.ndarray, optional - Fatigue damage (Palmgren-Miner sum) for each stress range bin. Returned if `retbin=True`. - - Raises - ------ - ValueError: - If thickness is given but thickness correction not specified for S-N curve. - AssertionError - If parameter `sn` is not a dict, a callable, or a class instance with callable method `n()`. + def igf(a, x): + """ Incomplete gamma function """ + return gammainc(a, x) * gammafunc(a) - Notes - ----- - .. versionadded :: 4.7.0 + if th is not None: + try: + # include thickness correction in SCF + scf *= self.thickness_correction(th) + except ValueError: + raise - Parameter `sn` may now be a callable (function) that calculates the fatigue capacity - (number of cycles to failure) for a given stress range. It must accept array input, and return array output. - To pass additional arguments to this function, use the `args` and `kwargs` keywords. - """ - srange = np.asarray(srange) - count = np.asarray(count) - if not srange.shape == count.shape: - raise ValueError("`srange` and `count` must have same shape") - - if kwds is None: - kwds = dict() - - if isinstance(sn, dict): - sn = SNCurve("", **sn) - - if isinstance(sn, SNCurve): - # handle SNCurve instance as special case, for backwards compatibility - if th is not None and (sn.t_exp is None and sn.t_ref is None): - raise ValueError("thickness is specified, but `k_tickn` and `t_ref` not defined for given S-N curve") - damage_per_bin = td * count / sn.n(srange * scf, t=th) - else: - assert th is None, "Parameter 'th' is only accepted if 'sn' is a dict or an SNCurve instance. " \ - "For other cases, use parameter 'args' or 'kwds'." - if callable(sn): - func = sn - else: - func = getattr(sn, 'n', None) - assert callable(func), "Parameter 'sn' must be dict, callable or class instance with callable method 'n'" - damage_per_bin = td * count / func(srange * scf, *args, **kwds) + # todo: verify implementation of thickness correction + # scale Weibull scale parameter by SCF (incl. thickness correction if specified) + q *= scf - # total damage is sum of damage per stress range bin - d = sum(damage_per_bin) + if self.is_bilinear(): + # gamma functions + g1 = cigf(1 + self.m / h, (self.s_switch() / q) ** h) # complementary incomplete gamma function + g2 = igf(1 + self.m2 / h, (self.s_switch() / q) ** h) # incomplete gamma function + # fatigue damage (for specified duration) + d = v0 * duration * (q ** self.m / self.a() * g1 + q ** self.m2 / self.a2() * g2) + else: + # single slope S-N curve, fatigue damage for specified duration + d = v0 * duration * (q ** self.m / self.a()) * gammafunc(1 + self.m / h) - if retbins is True: - return d, damage_per_bin - else: return d - - -def minersum_weibull(q, h, sn, v0, td=None, scf=1., th=None): - """ - Fatigue damage (Palmgren-Miner sum) calculation based on (2-parameter) Weibull stress cycle distribution and - S-N curve. Ref. DNV-RP-C03 (2016) eq. F.12-1. - - Parameters - ---------- - q: float - Weibull scale parameter (in 2-parameter distribution). - h: float - Weibull shape parameter (in 2-parameter distribution). - sn: dict or SNCurve - Dictionary with S-N curve parameters, alternatively an SNCurve instance. - If dict, expected attributes are: 'm1', 'm2', 'a1' (or 'loga1'), 'nswitch'. - v0: float, - Cycle rate [1/s]. - td: float, optional - Duration [s] (or design life, in seconds). Default is 31536000 (no. of seconds in a year, or 365 days). - scf: float, optional - Stress concentration factor to be applied on stress ranges. - th: float, optional - Thickness [mm] for thickness correction. If specified, reference thickness and thickness exponent must be - defined for the S-N curve given. - - Returns - ------- - float - Fatigue damage (Palmgren-Miner sum). - - Raises - ------ - ValueError: - If thickness is given but thickness correction not specified for S-N curve. - """ - def cigf(a, x): - """ Complementary incomplete gamma function """ - return gammaincc(a, x) * gammafunc(a) - - def igf(a, x): - """ Incomplete gamma function """ - return gammainc(a, x) * gammafunc(a) - - if not isinstance(sn, SNCurve): - sn = SNCurve("", **sn) - - if td is None: - td = 3600. * 24 * 365 - - if th is not None: - try: - # include thickness correction in SCF - scf *= sn.thickness_correction(th) - except ValueError: - raise - - # todo: verify implementation of thickness correction - # scale Weibull scale parameter by SCF (incl. thickness correction if specified) - q *= scf - - if sn.bilinear is True: - # gamma functions - g1 = cigf(1 + sn.m1 / h, (sn.sswitch / q) ** h) # complementary incomplete gamma function - g2 = igf(1 + sn.m2 / h, (sn.sswitch / q) ** h) # incomplete gamma function - # fatigue damage (for specified duration) - d = v0 * td * (q ** sn.m1 / sn.a1 * g1 + q ** sn.m2 / sn.a2 * g2) - else: - # single slope S-N curve, fatigue damage for specified duration - d = v0 * td * (q ** sn.m1 / sn.a1) * gammafunc(1 + sn.m1 / h) - - return d - diff --git a/test/test_fatigue_sn.py b/test/test_fatigue_sn.py index 875bb05c..8720eefe 100644 --- a/test/test_fatigue_sn.py +++ b/test/test_fatigue_sn.py @@ -8,7 +8,7 @@ from collections import OrderedDict, defaultdict from scipy.optimize import brenth, brentq from scipy.special import gamma -from qats.fatigue.sn import SNCurve, minersum, minersum_weibull +from qats.fatigue.sn import SNCurve # todo: include tests for thickness correction of SNCurve class # todo: include test for minersum() (fatigue minersum from stress range histogram) @@ -20,24 +20,27 @@ def setUp(self): Common setup for all tests """ # define sn curve parameters - self.sndict_studless = dict( # single slope S-N curve, here: DNVGL-OS-E301 curve for studless chain + self.sndict_studless = dict( + # single slope S-N curve, here: DNVGL-OS-E301 curve for studless chain name="Studless chain OS-E301", - m1=3.0, - a1=6e10, + m=3.0, + b0=np.log10(6e10), ) - self.sndict_B1_air = dict( # two slope S-N curve, here: DNVGL-RP-C203 curve B1 in air + self.sndict_B1_air = dict( + # two slope S-N curve, here: DNVGL-RP-C203 curve B1 in air name="B1 air", - m1=4.0, + m=4.0, m2=5.0, - loga1=15.117, - nswitch=1e7, + b0=15.117, + n_switch=1e7, ) - self.sndict_C_sea_cp = dict( # two slope S-N curve, here: DNVGL-RP-C203 curve C in seawater with CP + self.sndict_C_sea_cp = dict( + # two slope S-N curve, here: DNVGL-RP-C203 curve C in seawater with CP name="D seawater cp", - m1=3.0, + m=3.0, m2=5.0, - loga1=12.192, - nswitch=1e6, + b0=12.192, + n_switch=1e6, ) # initiate sn curves self.sn_studless = SNCurve(**self.sndict_studless) @@ -51,12 +54,12 @@ def test_sncurve_initiation_bilinear(self): b1_air = self.sn_b1_air c_sea = self.sn_c_sea # check that correct value of log(a2) is calculated at initiation - self.assertAlmostEqual(b1_air.loga2, 17.146, places=3, + self.assertAlmostEqual(b1_air.loga2(), 17.146, places=3, msg="SNCurve initiation, wrong value for log10(a2) (curve B1 air)") - self.assertAlmostEqual(c_sea.loga2, 16.320, places=3, + self.assertAlmostEqual(c_sea.loga2(), 16.320, places=3, msg="SNCurve initiation, wrong value for log10(a2) (curve C sea cp)") # check that correct value of Sswitch (or "fatigue limit") is calculated at initiation - self.assertAlmostEqual(b1_air.sswitch, 106.97, places=2, + self.assertAlmostEqual(b1_air.s_switch(), 106.97, places=2, msg="SNCurve initiation, wrong value for sswitch (curve B1 air)") def test_sncurve_n(self): @@ -79,22 +82,22 @@ def test_sncurve_fatigue_strength(self): """ b1_air = self.sn_b1_air c_sea = self.sn_c_sea - self.assertAlmostEqual(b1_air.fatigue_strength(1e7), 106.97, places=2, + self.assertAlmostEqual(b1_air.strength(1e7), 106.97, places=2, msg="Wrong fatigue strength at 1e7 cycles calculated for S-N curve B1 air") # note: for C (sea, cp), RP-C203 says fatigue limit 73.10 at 1e7 cycles - self.assertAlmostEqual(c_sea.fatigue_strength(1e7), 73.11, places=2, + self.assertAlmostEqual(c_sea.strength(1e7), 73.11, places=2, msg="Wrong fatigue strength at 1e7 cycles calculated for S-N curve C sea cp") def test_sncurve_sswitch(self): """ - Test that attribute that fatigue limit at 'sswitch' is equal to 'nswitch' - (to verify calculation of 'sswitch' at initiation) + Test that attribute that fatigue limit at 's_switch' is equal to 'n_switch' + (to verify calculation of 's_switch' at initiation) """ b1_air = self.sn_b1_air c_sea = self.sn_c_sea - self.assertAlmostEqual(b1_air.n(b1_air.sswitch), b1_air.nswitch, places=8, + self.assertAlmostEqual(b1_air.n(b1_air.s_switch()), b1_air.n_switch, places=8, msg="Wrong 'sswitch' calculated for S-N curve B1 air") - self.assertAlmostEqual(c_sea.n(c_sea.sswitch), c_sea.nswitch, places=8, + self.assertAlmostEqual(c_sea.n(c_sea.s_switch()), c_sea.n_switch, places=8, msg="Wrong 'sswitch' calculated for S-N curve C sea cp") def test_minersum(self): @@ -102,25 +105,26 @@ def test_minersum(self): Test that correct fatigue Miner sum is calculated using bilinear S-N curve. """ c_sea = self.sn_c_sea - start, stop = c_sea.fatigue_strength(1e7), c_sea.fatigue_strength(1e5) + start, stop = c_sea.strength(1e7), c_sea.strength(1e5) srange = np.linspace(start, stop, 20) # stress range histogram d = 0.5 # target damage count = np.array([c_sea.n(s) for s in srange]) / srange.size * d - self.assertAlmostEqual(minersum(srange, count, c_sea), d, places=8, - msg="Wrong fatigue life (damage) from minersum()") + total_d, _ = c_sea.minersum(srange, count) + self.assertAlmostEqual(total_d, d, places=8, msg="Wrong fatigue life (damage) from minersum()") def test_minersum_scf(self): """ Test that correct fatigue Miner sum is calculated using bilinear S-N curve. """ studless = self.sn_studless - start, stop = studless.fatigue_strength(1e7), studless.fatigue_strength(1e5) + start, stop = studless.strength(1e7), studless.strength(1e5) srange = np.linspace(start, stop, 20) # stress range histogram d = 0.5 # target damage (excl. SCF) scf = 1.15 # stress concentration factor d_scf = d * scf ** studless.m # damage incl. SCF count = np.array([studless.n(s) for s in srange]) / srange.size * d - self.assertAlmostEqual(minersum(srange, count, studless, scf=scf), d_scf, places=8, + total_d, _ = studless.minersum(srange, count, scf=scf) + self.assertAlmostEqual(total_d, d_scf, places=8, msg="Wrong fatigue life (damage) from minersum() with SCF specified") def test_minersum_weibull_bilinear(self): @@ -139,9 +143,9 @@ def test_minersum_weibull_bilinear(self): v0 = 0.1 # mean stress cycle frequency for h in (0.8, 1.0, 1.1): q = _q_calc(life, h, v0, sn) - self.assertAlmostEqual(minersum_weibull(q, h, sn, v0, td=31536000), dyear, places=6, - msg=f"Wrong fatigue life from minersum_weibull() for bilinear S-N curve and" - f" shape={h}") + total_d = sn.minersum_weibull(q, h, v0, duration=31536000) + self.assertAlmostEqual(total_d, dyear, places=6, + msg=f"Wrong fatigue life from minersum_weibull() for bilinear S-N curve and shape={h}") def test_minersum_weibull_singleslope(self): """ @@ -159,7 +163,8 @@ def test_minersum_weibull_singleslope(self): v0 = 0.1 # mean stress cycle frequency for h in (0.8, 1.0, 1.1): q = _q_calc_single_slope(life, h, v0, sn) - self.assertAlmostEqual(minersum_weibull(q, h, sn, v0, td=31536000), dyear, places=6, + total_d = sn.minersum_weibull(q, h, v0, duration=31536000) + self.assertAlmostEqual(total_d, dyear, places=6, msg=f"Wrong fatigue life from minersum_weibull() for linear S-N curve and shape={h}") def test_minersum_weibull_scf(self): @@ -171,15 +176,15 @@ def test_minersum_weibull_scf(self): scf = 1.15 life = 100. dyear_scf = (1 / life) * scf ** sn.m # only correct for linear (single slope) S-N curves - life_scf = life / scf ** sn.m v0 = 0.1 # mean stress cycle frequency h = 1.0 q = _q_calc_single_slope(life, h, v0, sn) - self.assertAlmostEqual(minersum_weibull(q, h, sn, v0, td=31536000, scf=scf), dyear_scf, places=6, + total_d = sn.minersum_weibull(q, h, v0, duration=31536000, scf=scf) + self.assertAlmostEqual(total_d, dyear_scf, places=6, msg="SCF not correctly accounting for by minersum_weibull()") -def _q_calc(fatigue_life, h, v0, sn, method='brentq'): +def _q_calc(fatigue_life, h, v0, sn, method="brentq"): """ Calculate Weibull scale parameter (q) that gives specified fatigue life using closed form expression in DNV-RP-C03 (2016) eq. F.12-1. @@ -207,8 +212,10 @@ def _q_calc(fatigue_life, h, v0, sn, method='brentq'): ----- If thickness correction was taken into account when establishing fatigue life, this is implicitly included in the scale parameter calculated. To obtain the scale parameter excl. thickness correction: - >>> q_ = q_calc(fatigue_life, h, v0, sn) - >>> q = q_ / (t / t_ref)**k + + >>> q_ = q_calc(fatigue_life, h, v0, sn) + >>> q = q_ / (t / t_ref) ** k + where `t` is the thickness, `t_ref` is the reference thickness, and `k` is the thickness exponent. Keep in mind that ``t = t_ref`` if ``t < t_ref``. @@ -217,8 +224,8 @@ def _q_calc(fatigue_life, h, v0, sn, method='brentq'): q_calc_single_slope """ rootfuncs = { - 'brentq': brentq, - 'brenth': brenth, + "brentq": brentq, + "brenth": brenth, } if method not in rootfuncs: raise ValueError("method must be either of: %s" % ', '.join(["'%s'" % k for k in rootfuncs.keys()])) @@ -227,15 +234,15 @@ def _q_calc(fatigue_life, h, v0, sn, method='brentq'): raise ValueError("`sn` must be dict-like or SNCurve instance") if not isinstance(sn, SNCurve): - sn = SNCurve("", **sn) + sn = SNCurve(**sn) # fatigue life in seconds - td = fatigue_life * 3600. * 24 * 365 + duration = fatigue_life * 3600. * 24 * 365 # calculate gamma parameters eps = np.finfo(float).eps # machine epsilon func = rootfuncs[method] - q = func(lambda qq: minersum_weibull(qq, h, sn, v0, td) - 1, a=eps, b=1e10) + q = func(lambda qq: sn.minersum_weibull(qq, h, v0, duration=duration) - 1, a=eps, b=1e10) return q @@ -269,12 +276,12 @@ def _q_calc_single_slope(fatigue_life, h, v0, sn): raise ValueError("`sn` must be dict-like or SNCurve instance") if not isinstance(sn, SNCurve): - sn = SNCurve("", **sn) + sn = SNCurve(**sn) # fatigue life in seconds td = fatigue_life * 3600. * 24 * 365 # calculate q - q = (v0 * td / sn.a1 * gamma(1 + sn.m1 / h)) ** (-1 / sn.m1) + q = (v0 * td / sn.a() * gamma(1 + sn.m / h)) ** (-1 / sn.m) return q From cff75cb78f377f657b4e7a7659ba970de6cf98fa Mon Sep 17 00:00:00 2001 From: tovop Date: Tue, 22 Jun 2021 11:11:03 +0200 Subject: [PATCH 2/3] Removed unused import. --- qats/fatigue/sn.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/qats/fatigue/sn.py b/qats/fatigue/sn.py index 2f67e16f..859c2a8f 100644 --- a/qats/fatigue/sn.py +++ b/qats/fatigue/sn.py @@ -5,7 +5,7 @@ """ import numpy as np from scipy.special import gamma as gammafunc, gammainc, gammaincc -from typing import Optional, Tuple, Union +from typing import Tuple, Union class SNCurve(object): @@ -18,29 +18,29 @@ class SNCurve(object): Slope of first leg of the curve b0: float Constant coefficient in equation to calculate the intercept parameter - name : Optional[str] + name : str, optional Name/identifier - description : Optional[str] + description : str, optional Description of the curve - unit: Optional[str] + unit: str, optional Unit of measure for the stress ranges e.g. MPa - b1: Optional[float] + b1: str, optional Mean stress coefficient in equation to calculate the intercept parameter - b2: Optional[float] + b2: float, optional Corrosion grade coefficient in equation to calculate the intercept parameter - default_g1: Optional[float] + default_g1: float, optional Default value of g1(s_m) function, where s_m is the mean load - default_g2: Optional[float] + default_g2: float, optional Default value of g2(c) function, where c is the corrosion grade - m2: Optional[float] + m2: float, optional Slope of second leg of the curve, applies only to bi-linear curves - n_switch: Optional[float] + n_switch: float, optional Point (in terms of number of cycles to failure) where the slope changes, applies only to bi-linear curves - fatigue_limit: Optional[float] + fatigue_limit: float, optional Fatigue limit in terms of stress range - t_ref: Optional[float] + t_ref: float, optional Reference thickness for thickness correction - t_exp: Optional[float] + t_exp: float, optional Exponent for thickness correction Notes From ee902f9e67f6fd3bb97abdfa7c680488658a1e70 Mon Sep 17 00:00:00 2001 From: tovop Date: Fri, 3 Sep 2021 13:08:39 +0200 Subject: [PATCH 3/3] Add examples using the new mean load and corrosion dependent S-N curve. --- docs/source/examples.rst | 20 +++++++ docs/source/examples/mooring_fatigue.py | 7 +-- .../examples/mooring_fatigue_mean_load.py | 54 ++++++++++++++++++ .../img/damage-contribution-aggregated.png | Bin 0 -> 49334 bytes .../source/img/damage-contribution-single.png | Bin 0 -> 36932 bytes qats/fatigue/sn.py | 2 +- 6 files changed, 78 insertions(+), 5 deletions(-) create mode 100644 docs/source/examples/mooring_fatigue_mean_load.py create mode 100644 docs/source/img/damage-contribution-aggregated.png create mode 100644 docs/source/img/damage-contribution-single.png diff --git a/docs/source/examples.rst b/docs/source/examples.rst index 7c0faa17..8fb279fc 100644 --- a/docs/source/examples.rst +++ b/docs/source/examples.rst @@ -96,11 +96,31 @@ Compare the cycle range and range-mean distribution from several time series usi Calculate fatigue damage in mooring lines ***************************************** +Using a traditional S-N curve with constant slope and intercept. + .. literalinclude:: examples/mooring_fatigue.py :language: python :linenos: :lines: 1- +Using a novel S-N curve with mean load and corrosion dependent intercept parameter as described in OMAE2021-62775. + +.. literalinclude:: examples/mooring_fatigue_mean_load.py + :language: python + :linenos: + :lines: 1- + +.. figure:: img/damage-contribution-single.png + :figclass: align-center + :target: _images/damage-contribution-single.png + +Note that this figure is based on cycles from a single time series. The figure below illustrates more clearly how this +can look like when using cycles aggregated from years of history. + +.. figure:: img/damage-contribution-aggregated.png + :figclass: align-center + :target: _images/damage-contribution-aggregated.png + Apply low-pass and high-pass filters to time series *************************************************** diff --git a/docs/source/examples/mooring_fatigue.py b/docs/source/examples/mooring_fatigue.py index 08198a71..e5998ae9 100644 --- a/docs/source/examples/mooring_fatigue.py +++ b/docs/source/examples/mooring_fatigue.py @@ -1,8 +1,7 @@ """ -Calculate mooring line fatigue. +Calculate mooring line fatigue using Rainflow counting and a traditional S-N curve. """ import os -import numpy as np from math import pi from qats import TsDB from qats.fatigue.sn import SNCurve @@ -23,8 +22,8 @@ ranges, _, counts = cycles.T # calculate cross section stress cycles (shown here: 118mm studless chain, with unit [kN] for tension cycles) - area = 2. * pi * (118. / 2.) ** 2. # mm^2 - ranges = np.array([r * 1e3 / area for r in ranges]) # MPa + area = 2. * pi * (118. / 2.) ** 2. # mm^2 + ranges = 1e3 * ranges / area # MPa # calculate fatigue damage from Palmgren-Miner rule (SCF=1, no thickness correction) damage, _ = sncurve.minersum(ranges, counts) diff --git a/docs/source/examples/mooring_fatigue_mean_load.py b/docs/source/examples/mooring_fatigue_mean_load.py new file mode 100644 index 00000000..fb2b618b --- /dev/null +++ b/docs/source/examples/mooring_fatigue_mean_load.py @@ -0,0 +1,54 @@ +""" +Calculate fatigue damage using a mean load and corrosion dependent S-N curve. +Plot cycle amplitude and mean versus contribution to total damage. +""" +import numpy as np +import matplotlib.pyplot as plt +from qats import TsDB +from qats.fatigue.rainflow import mesh +from qats.fatigue.sn import SNCurve + + +# mooring chain properties +mbl = 10000. # minimum breaking load +diameter = 110. # mm +grade = 3 # corrosion grade +area = 2. * np.pi * (diameter / 2) ** 2. # mm^2 + +# S-N curve (mean load and corrosion dependent fatigue capacity, ref. OMAE2021-62775) +sn = SNCurve( + m=3, # inverse slope + b0=11.873, # Constant in equation to calculate intercept parameter + b1=-0.0519, # Mean load coefficient in equation to calculate the intercept parameter + b2=-0.109, # Corrosion coefficient in equation to calculate the intercept parameter + default_g1=20., # default mean load / MBL ratio (%) + default_g2=1., # default corrosion grade (1=new) +) + +# tension history +db = TsDB.fromfile("../../../data/mooring.ts") +ts = db.get("Mooring line 1") + +# rainflow counting and meshing the cycle distribution (for plotting) +cycles = ts.rfc() +ranges, means, count = mesh(cycles, nr=25, nm=25) +count *= 31556926. / ts.duration # scale annual cycle count +stress_ranges = 1000. * ranges / area # MPa +total_damage, damage_per_bin = sn.minersum(stress_ranges, count, g1=means / mbl * 100., g2=float(grade)) + +# plotting cycle amplitude and mean versus damage contribution +# cycle mean and amplitude (half the range) normalized on MBL in % +a = 100. * 0.5 * ranges / mbl +m = 100. * means / mbl +d = 100. * damage_per_bin / total_damage +cbar_min, cbar_max = np.floor(np.min(d)), np.ceil(np.max(d)) +cbar_labels = np.linspace(cbar_min, cbar_max, 6) +fig1, ax1 = plt.subplots() +contour_ = ax1.contourf(a, m, d, 400) +ax1.set_xlabel("Cycle amplitude [%MBL]") +ax1.set_ylabel("Cycle mean [%MBL]") +cbar = fig1.colorbar(contour_) +cbar.set_ticks(cbar_labels) +cbar.set_ticklabels(cbar_labels) +cbar.set_label("Damage [%]") +plt.show() diff --git a/docs/source/img/damage-contribution-aggregated.png b/docs/source/img/damage-contribution-aggregated.png new file mode 100644 index 0000000000000000000000000000000000000000..3fb20afda4545f10c1ff39dedde39487e3b1e644 GIT binary patch literal 49334 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 literal 0 HcmV?d00001 diff --git a/docs/source/img/damage-contribution-single.png b/docs/source/img/damage-contribution-single.png new file mode 100644 index 0000000000000000000000000000000000000000..8932685c57eff27b4f97494e3fc1ca2139d42209 GIT binary patch literal 36932 zcmeEuWmuG5xbDml(v2X}NJ|P5(ya*6B`GZ}pmYx1ih_XBAuS<@bSl!_DGf46_gSys zxA)n5U+2g9b$%Val$e=!-nG^f_j5n@GZAX4iugEGI4~Ft|Dlqc1`LJ>fWhDkSeW29 zf`c=^z!woWc|A8xCo8vCW-lyZDrRoZ_D*j0w$JEaTE1|#b#lDN4gTJxw{dfGb`|B} zarn_O~A_E*F<~0WR-5D}{rywP|z-{`wOl#5Ho?0uMY zcII{B(^wU!si6^6QBi?sNW8*`*(`8z+;lBp<2ajg#vdNe7H2>G1>fk~%iiwKTU%R$ zMT*K=I|D-!I{B&}$}NB13~feqz>-6CN(|sI)%N$O=IM4_Svk3{cVUuqEp|t{vG%A_ zpMt4Ov!7?QY))^z-n#5c&@^CP!P5J?V0sypuwhfdbFYOEMaZDk@rF(YD2+n9pR(Ix zNOAc5H5&|tH=+XX=dQFS{u&ofGyyivC)Q@Squh(;Gv0s93@YY*epbwG(8z1WTfhWgAAE`FbzC=1j}DjErtx6 zobor-jTs3z3}~=XR9e+9~m`IsbF5>|7BX;Sav-l7D@IoKl7ApJ%a{ z{^J@rf8S=2o+vU5vVU-&L<96gQ|UOjQv?3-7Eb7T7z#<9Odl>kmGk{`2VA`@3x5~+ z->+ka5x?};tvGn=$ObH_vIB-ElK!Cm_e+JUH2>%FGNhEV6Q2BBs8(})_RqHP_euo3 z_J!fnp8xB_I*`}m;GM%X{#~=e8ytc63UpH37`mtl^vB@tv@G=CfA>@r{XpQkn5Z7& zuG_!+;|pV_y$>h-8xH=t(&MvWsR?w$^?wg+@CNUp)y)54ErY{`xXIZ8xOD%Vgc+UG ze{PYQFd=os-#|1s`MPa1VoU_5cH!Uc zgbwt7oH5Nt%&*aVuh>L~ ze9uhJk9LlhKfIdz(YXTc@=9X84T4tiIhjHX)mzk2rB&|>U*GG?nA@}8#t-Qk8M_6?-tR-@) z-@~N!-sZEPtiWLX;6`$^Gfi`qpaOi)WvJPP7tRkp+B*8Q~S zpB<*Zbk<@(4i()UB@yt+px%S8v~~%n{$NO%lJA*Zj{|i3vIHXN^M2@pwS9ZC zk`L^PmbNw=mLg~u8X1WLYmO0`3x~`_F^=|R*Z(?dV>n+{TRWOgvT@JpZyF_Dk#9Gt zaiqb-qcnZ8$nUzQHCwkJN@jF-~P`Ct128_aZZiUm=-O(49APHW;%7DCv5f>((>yRp%EQD%JH zso_v(#+=)@UbwdiY-YF0#{K0A>{`@6CT|;2ZBaD8+r?Eg6V&K?o+Tf36G|2=kCOwg zua28s;vT&EZFsOfNor|nNhx4MByoXiyE`ZE@^3t%8gjr?RV`+Idb~RyhkyJ2Lf?bk z_E7xW2}+X)j86I1^oyo>a8u)v*wKW!Elt!=8%)ohqy)u> zPC~rGWlhdAdI`^{uNQm%mRn!v`ddD z+Y@uTk6$~?S-OJEXc<6$)p)vk`(i)+TJGD+oo9|FAkzn;-FUXr{r1Qe!~*aY1T5z- zJT+|P2)(-+_^!p!+tL`}tn(kTELa@JR9o1s^?le&oxi}mec!&hsH_o3Wq8}q2Xcjn z53ykjBbrY-Jl8&i*_D394EVe`-X1~f(!c5; zpq!kid@zD5MxoK-*a&QXC?TDrzc{dbSTpp}u|NTwS_kevQeG4osjr=nIqs`>K+R&^MggGlkL5; zk2y?PIp1v}^!}Y@lm8H+ner(Kp;!D-luOigV;dN@ zL8w}rbQ4|>P(*3TQn%58@YP}l?B~u?Y>N{n#%|>lvVkF+P8H}$cmW+OgGAp^;I%aq zH$Yw{b>@qt_)U2QFfa}kXFvys0dxFfTsYhA!%tFA%-MzCcQz){QNp71ZLpw=abQuQ z3*>h^w4ia`9Tl_qiR-$eS+itZoW1EFp31gv%2gJost zPNGjhf&l>gUv%?UitS&>(k2l=M%dK$Umwk8>a7kC!OHoM%=mtl&GZLM?|&xxy2q8+ zP;#dICpj;&nMQ`qoBdZvV@Ar`@$bFX-h{qQ-bGGE@*L(h5P;Bfs~EtEZM5WmB+02O z^fF34c#q;>>qj*`Y!H-nVC>wO%|4`MLy&uE9Z&)k@#XgF8@W`^Nopwn@|7c!2{o|Y zAd4jD0#B#KY&J|%6^vs-MubPcmh;m5`n|^pXN3*3`Pl+q0$wn*0da8NB+G0bx;A=n zZ03LOPp^j(Ga?*^1dYC;b+A^FMa{;|P=<&vs7Fc%}yS?$iCZd^^K4iG)@RG>o{SF0$@f@;vTV(BDSOZJW&kAYM zn`S1*yoG?Ul#T-0Li+W^TF&uT5R?WBwTm7bD_lJ)KU>4`fB5)_nu=-}Q%3cUidq&|jOog&&}q_gH$o)F`v?xy-Z^0N&Og+;5_pk}!rg4fF@*pqcgXet!;@W(+|k z)@7Au5CdhqVrfXH-nH~I1a6vS^){MyDf8k%9zaYU7LC~qa!$78&v)2P{?iUMnZRw| z*CQ_yADt*$%{8JI1w#%Q5*RGS_A$Ee>H!GJ0#0*ci#z!$si7c!cg_CZshRIg<})A2 zRi?mVD0kZ!N}lG?uRzcL@RCZ@Z9U-6pBH$vVw69VcnGH*f6shfpR8orK6qr@u%O6BF-LKl#5!L=C+Fsswz} z%zt)vurX0?h6drN1SZ92U>6=5J)K%YFN_XrQd%PvVUdM!x0&66t!Yl;fB@GgUx1fF z0Nh}%zXXBF&}82K`qE?Ntu89g{{jsS6AuOx`}3Wt_D?sb%SLVz0=C+l8U}XG?CRpQ z_HgX!o4UqCLHCm=H~Y$nq}~=exzi|svY)6YzHl?@0@-r=DpVq!aBIA*E1Z~V+ks5J z1$-@kxieMJWou*83^J8boW1P`ieg1fhWK+);NM7l=e^ZF51Q#BXXN|>q2vYc^XJcb zUvBHcnx9BsqN@z6>FaMyl~z=cfIz1nch9^NPfJT{A`T>>TtD>3p9nLe`9QkxK?tT1Qg$tc!`e2$&CdI@2K6a%@ zayVPQ5{y5_a&dU#?H{>LG*e(!3~~oBrrhXLFBUH2dP-eG7Yt*s4Q5?eCxA;b3poml zij1apb#=1=##E2fH86-A8X7v_=14lb>}Z4BBgqX5s}x;^&q54VYTO_?9QODJgt&fk zf5VHS;OSf+%r+`}o0w?2&>X1u^#yaE_^}~OL9*p7r|uGn)wV%JF^oS>;cpDKgx=dJ zv7l2?yguCmm^3T;hX;&W)XgT3Fd`*|%IAEi=4kxs7yFhxmDGVR4o}^7=V*rWRNCSs zufnaemfWwzvBE*&~6NmoSYo?*M^qbBZOCz&HuuQv10v#l9Fmg z3~Tv!seY9=G2dVZ5`ST3%y~neRH%(T~{}ZK{hl)CH4NpohHXwQ9L?{ znX9SIFd^_h5GtOoaq0rTvooIVv4o9|fIm(Vz<$G`QjuQsaB%SAtu-^%4+=fL z-@`ny%kw_cOo1~f)|BG77V>*oK)}H=SACGU_Ys6JIM>Skcn&=mSqgeJcPmSGoSLnd zuM$V?a`WEq5n~F?c`%KY8b#r9*TT~M&e;2em+=7BskR$m3MQ0j2Dl^^6f)w&`MpNA zI)C`9pUj9{zJ8#$)U_hO2O_fw6s^jdu0(Hg86Y!d!{=%8?A`B= zK9MrZUQeA?)P@rDPQ+SV6XOlA&ovM1sGt`*bpG#Sx zK@iwy7w@&L-qmNP@=KJ|v+R$!)(a7F#%@?PBDs$~9?uwWB`5lZl%2>I4*=2QH#9Zx z+`>WHraySkn>@lkbKU$v#M^~?77y$od-_opp^}S~(&Gyo6>f=8rG`*+hyPMca7ij-sSgcGCUnM8ZZaUts zx<*s`TyT8cvlYirMjNgT@A3X#b55T%!*CC!GzOw5uVpvc!TKOtZ;D`BJcBH1P?4@< zX04=Vt`&S2Gc=@e@O$<)E(Q1F#h%2-XkD1(`Sv{@RLhNINq-4diBk*c;Up735$<}F zOet$}kU}aqOLsI9b$SOpP^8#BNBL_()TKugy z47!&gGL>d1;N5qci-ryss)4R{udfK9(qJv!KNgKZnBM-J>**I$aI3YOg+(Y()0zP= zUAq*?Iq=ohI+|L9KX>cu*PAD==hniRVgtG~ePkJt(POHqaCdii50GEVO-Y zapeQGO5(e`Mk#mh&o^gjLtPh$=c3Cl64dtdt5sNJ3=-oLMq!kSBLg>TgVNQa$8$<= zHzc`Zf3l5Fc~`mkLwiM&9II@+mW~~+a__hNu$hWF9-4+H7;vj(?? zdo|Jy#_#^PR9zmP9Jim7HjdTRiB>%y#VM=*gQE~f>mVuVydV`#C5YpH(ni;M^mXOk z({lSse*3xlNx$DgxZKS=O&38>9LU|$A;XXfFEAQlbhthoH(72*BYeE!b9%QZp+>*b zDw)>|;dQhf0icKZ-cm>MJ!{n#^kxMLt_u;#{)Mwf6$VG8FXv|>LFq&Rw_qVe3VIr_ zKx!H_;wh~iEPokoh7wyhWB@vViCHX_uXc^c$8&RYiT%TFAmAY4RPeuAw;wCMH3zDW z@Gj$TFS!(=DHpvQe|=9#=C^!gFn-Z;gDyihjKHPljmFY)-1IK>}v20 z!cOo*SR0`vH7Eu>u1?oJzuYkZ2Kr!$y|Azl%I#iIZU=!x-pGgsumZJnKMRL!&uN}&vTWA#7RV)Fj^h9th)tST} zR*QFWW9MRA;sUlLLb50qe|Q-aD|jI2OY#>90*AJ5Pvi`@>oNI~6N_AYdc?cXx{c(L z)5Agv6s5_@sarf}j)w}YNnFBy*Hf;p>jQ0}mE#Z^9_~F!7 z#bqC^yYdb2?U5X&GA%s6t_-y$tx>M_JUPxc@(r;A85a9XVFqZDa=c_y-(c|ru!2$| zHbJQZQ>;5##hg4mPimW%q;Jq5K_Z8a5!yYFQ288ZY6~v6L_sVD)$q9M=;$aL4^RIi z?NacZlsp%yLUv9&I4(oE&0to+G!_FTOp~1JLce&;wTdeFB?@hO)%d{$_9B65Ar+o# zBx2)O$N|f(Z*R^13LoD;QXj+3rwkp2bqmjb%++ci4?s)#p+r*Y8k<1`mqAtY@7Zsk zeNJD99Sq14*W3mbwH}6JMcP={JgmjJ-K;FS&4!I0_)_u-ud-`W3USnxMmawB{ z-Y+WEu?{_%3Zg755`22`QE68{<^4`uy9 z$oQo4>_#EZg1XUL=^_K0!`oFUuSLuRh*uzZVmg%b5F%1}&05jZJeDH#8hu3Sjd}i( zWD|AnMGd}X#tl%c0t^uXB9waG-`fMsM6TG4jFmLkz7_xnZTuTt*HqJdk0x#A>O}zW z69a<5z2c3pl$O4$Z9CI7%Tsn`9l#4SY^hX*7tsM^{DxYcd017LwE1~S>qic4_UpIL z1$lcpOlKm~-5pAOThCA7SlkI#7~)&*=Uef4j;`F|*33kORCCcOCArHoZRzA%9~S$G z9Wx6`rRibO&-1!C_HP|C!<0VBHroj}q#mQ&oHh{f6I*KKVFunY2TUI2gO~Or<4h%g z_yBEZKU2$h`liEqP@ZBjQB$=g=iwXYo$7H2A4{i8`0~1~tDRi>6&qCJ2+cUlD)hgP zt1!M_yIt|q`B#GCGmt@{lZ0Gxdj9JEGyrDmLC<>PDa+>RsC#qOg_J&1QNC!12%SWx zc*`mrO);=r#D~p3;jZGa31c6a-CUj3YrW;V{e zy&UDWV_r$3B*(4t`KDp4@b$(19zcOhkg@M|(Z!Lf3c~@#%mVFYn%mGrkNsXDmoA!D z0*99OzkH^w%4JBU%$ihHNqyA4eErqYv%g zP9AW#{8W~{R1nV|JJ=Ly9?8HEEoql_saw2i$`JhKZrjB%*RXO|$kC~*z+UJLeZ|T$ z&wdScdL+8QY`yNS8O8D7-I!7-oQ;AY4w!&>)%|biB#tcW z7_h7gVsV$E`dK5L)Y-66*C6m=OQJa9Q_0pSGZOFX%eBh~AKz%iO>_pJ&=q(R!^jT&(c;|2VKsHO^|`dVBct!{t;KtRa|`>CER*_gwb?(eZD%)5+io3Mod@wemf;I+U*$I&V^O| z{?SO+C9XGK8Zr}?NNjxX=yPmTysLAADdP+F)>RXjUX=}T-OHUwK)q)JUfkpIa2#TS z>p|J=0qAU~`XxX}zdM5+ZI0qX1%uz^mWeqawok6kclS_jgyx`7gN%)Vgr>uQo}{Gv zyAnBLf% z*|&B%v?AyR>ED8i-EK65w+z&dqfq&L7sSLOk5ljC@2~YMYHO40lp01n*sUjpIZv2{ zEkY>NHvhxBy|0-2>SJEfyHnM;6viG55@+j7z*mW(jL(|x^SWesB}vXtU1*iZ^_z*& z%OKAY)7v~)2Jjy^K||`7IQWtLd#E+CPY;DP-!_Lc4B)-`%o%7!k0<eX;$kbpybN~+h_j%$ST2l!W}wyRVff#$;sZo5MTg`YAUSST}}b4sowk+ zj&!%fR9CIx0CukYcBK!g)bPyj@8g))w9XWd!){iRzKf0$+Dh-TJ6KZz= z=mABQo4}u`xf@TG${j>sZcm`=zIzIg04r!#q&hX;IzQg+0%Sb|>0!;N#kS8N|9LbR zQ@f9-18?d3ske4vAJTkR7tZC98j`JrPWt@j7tX*RO+tMeR;?@ss;^qt2Z$&QMsZ8f z4Ho-d%5+XD=Wf{QTtoco3`F{iU7ajb@|wa{d)@~FI=JW)4?C-+4^=V<=H>vIgCeo* zmUUVnV2h^8-oAUc1c)AUmwq&x1g{Y_2KQUr))cl6jHsklx)aY(@|G&ZZ$dtq$xI$o z?py^dq_fIQTvCU)e~3ibkZ6SPy^RvId@MR%g5}y^ir;#hfAB>ese~L>Wzs~%MFzRhF@W2{jY@qdtg-GqXt+FPGPg1WyTsH>@Ous&B=ItKK z!t2*0hTc2X?+hQDP8H{w((m`SsL%`0-{y3iFrlP#-+!X%dWdJ2Wog%5 zs@1!?AUF9|Qg8y@kycsB?3&oV_(!I6v)B`blwfTvn@$loS6>sek9=+m;ev>ia5mx% zf?wZCcpsRKt)M-}QX@Q^AllKdvbvfxJV z+{9%|RJiT2Kmf8{gorf}dbFSSm|sMwl=X=#H&_1q<9u79!cBre8N!dOqzq~}%N~U| z8^0*LNDxX(qn4d&}QTqQQteg7M5QU!GQzBnC^DBZ&5#H zK+nnQA_&Y}>`yymjxN11j<4X1zZe}NHEY;L0Yj2(zifk=4OJGPYw^K8RZf?j>$v2xKvsSJEYQM*WEQ71+0h+w?i-DG&x0KATCu zccHJ+tZpHQZjc?Uef|*fV2jI=wHmg@-2!229F-{14rbs zwYpcXCiepEDYY3(!X=~AGL}!N1343~0fU-4j7Dnx8EqeGO+7gMspd~5Tl-~;MsPE1 za;q}*MBDS$M{v;i$f_cBmc<^gj%FK1J%EL{YHyaAeEPTnLO>a>JcurC9> zhWz_NL|!Y7*LxC%`a3jN&&26=c*njQFu=7b_cs_q5?Ug7i;yyy=d_RT6#|r5>vL~k z@O!4?Wy*Ofe_xn?^Xd1KkQg{`y8M~tZZXOIjw)VtnPBaPXiD^ZWClpa)}ov~A{+9x z;^U5NDp%B}!iEpxZhZzx<0;+)X&IB+iwzy#yDc#8$lt*S+CqurkW&80b9)_72cVIaYUyfxYui_t$R^PbQ zNQSWyj+Ys@$tF+VJe;;8c+i?|?j9T7`>oWLbck;^tqPs!enZbG(r>=gRo0lH|CQKd{qURapqK5?~Ex(Gvcxl9ImE!90Skyeu& zUJ7=yDMHt`q~-?HT}+ys=|seW34m-~1hqvcz(^q#75wL?#7qhcpzUkZ%J~z&IOJxe zJ+et58C$?$*tvC)*Ufh+nKM86t#Y${DL!^dWHnA06TLwu-%WX#1~viFU@^PBmUm=Q zv0!c}QnCoKImfb>exv9GhdYhhz(MbnTq4zdxH-^b0BfaizS!%M6~3a`21{)`|NV`n zzG5bR6ju9UQN`<0%XL9f*g`~A3-HJgym7+>(vgKGnM5;zjE z`fMrRSaCO5m9&~Aw1Vzj3(6Y%7TFSB;1RO_J%Ji1S7J2?Qd=?A=i&y^-^4p03sZJA zL*F$q0jd}l{^7x^EYQm~>mMH*t3#N5?lzbPn$?$JEI4;tNGsr=FMrX-gkS*uP0X=$>Qy&f|f(VpOnsrC6`C#R(vAEXXeNI30_Y?oM~FA`7IK9UjR1?n&l@Uh+5d1P9TS}R`q)UyASkRfq_ zsY=6!5T?HEAX}7j?q}@yjXWVpI3W?PUDmQml5=H8VBo6dg zuJ=63Fqe`ycq^r7(p0e6kK?GSKCirZMR}GIPn5zJ#t0klX1!HnLqcr%1EMDY5Ulvb z!^CRI1sfY5Uyfk?*erQ{`s841oY1&z{P2t^PV9Aw=32<(&|Ep0CwZ9u7LUJQ=1`yT zlLwVZKO)9dztf82KbFV~VrLJ_u$zo&70UW>t+Lgmm}NmplC>{AYG7Qjx8O`3J5V7+ z${g!Xx3nQPI^g}C+Sfve*tobrd;TGliMrzt1K0)Nk(@`=72z;IX>NPPWIK_N-lON> z^ZR5iljs+i+1r#kTyuxaemSJcLMDCrYM9`wPSbs2Yti>aFHc<4=E)J{u93-FvKga> zTWPDz1}Dmb+w#->IDs1I<5D+UN1GBD;@NI|CZvbd6!)CmcBaUa3}0a9JxM2E9*?{e zLvIInKHMCg6m{FP&1uxp=-?f!#`k#0jHi67-pN&vD6=p?i=+^w`=Jhptp*D$B=oELdn?84*1}9(5H-5 z=KhKfAyU`^Al?3QeGh)uq5;uLJNP*okjFDGryW#$s$=3vrPm4`>s<2>UEDs45`SxQ z@Cn(3t{}qd?mx6ywvOl9C+QyJd4bf1$Ef31r9K5!ya82TAqz*q0QoD@LMC*X$nT3k zQigdaQP$$Sbpw=vPvlN%v0$w(;;RS3>arQGOLl;X>4x`azw5D}!|EuxS3X6yLpBM?JyvVUcuFe*i zD9^f=m}xg#w3<|8@)#4n)H&@b+wsQLAJ=0;48U&XQ&IA{v0Et(ADCj1Ap&Rx(Pea7 z+ca}f`Iza!B!Ar3-D^1l2U|0i{jx5lGvVcRWScGCk(7ws0Nz)CSbOe;uswqJOuQBN z0GyQ&1PfemzvckA9$;5t<~iln3eKN@7}V(j(N!qktstJp69nLb`7it=B>?{pF%Y1o z_K;@l|IjRUns20Oy4-Pc`OXj~rB3$vJwLO3Y6vcc4A!ET@HkG7{zI*6WLA#xC2on2 z{%~AvY`SSPu6}7Rf#4*b|0)OVSX;_`zrpdipUNvIYp1fG3kSSMXDwDrct!89kI!>O zS@gcJ8WOzM>DUrvwIxuc+)3l;6x^#2Y^fZ#3zM{?qIhs1(!T=W)B)9p-EY+@>%S)Z zQ0oO^qBWJf9cQ;HV`GFz?Xnp21f0f3lGL>7+_yp@RK9%*{-*-8E*fkblz9$QRkqv8 zKe6?TU_fYf>2WZq$Y(or2V&1Ft@{-K`-J*7e@Oshzv`x5b#?Xne3K;iw{8B5P2Hx* zZ@#j!Xi&2pvPM9k*^KOT|NOZ(s%tW7LeagD7#(v$&UnHa#NF%sjNqc&fAZUnAi1J# z=9%$+(RYm7t5XB<*4q2XETj`@{uG5fQIrw3R>3&_>=-an^hv=$8Mw@!v^gd_mIJ0*1$F3*CK}8PjDf2vT%@Klo_ZA9U zZ|#(;3%6xdr(?RBba`8ZNZNf8TjOBYVIC#EDvsnx^^cel+nIvXOv%_WQ1QXC))nFD zP<^&pRE7cqzv+&TKrdhhumvP*fGvPuJGOG#8|dQ(0E1`&=>-P6LG27h)o3W!fW}h` zz+08>Q#m6eBarNGz@0{s&R5`f)3qNc8S>TpK76vOc#P3h%M?IbfQebg9JH^qG|S5mi*am-Ct*kN zJJXBiDyf@a<^*yudl*`)z5+EPEI%RHZYqtP{9K^I;rMGpYm7L;Ps9Lsx?P5o8x>!6I(6!cVfarC6=go8(&4$HKMo zvwY~uJVd_;wVF(?+Soh|I=hdv*$^{c7Rwn3gR)0%l5r%|)>zsyNVuMUTMe54N`rG( zd3EQlk{YWmty_zSUVNs_e_2fRn)mk|sPa@lJoj$^y({lK>SOXY{4cemvWjOC1T#mQ z^T;+XzEWPLJ<~!nYTWQz=< z757@G8djC{^b`Til^LNHmyUkw4QD`KuTR(TNSrL7-359hK|w)S0ATSchx4C2+0+9+ zPE^^F0-T2qo2anF1>aaanG*)W+{ekhE!A<=zCf!CsRV&aV-YaYH6~5Kq#%XF(){(6 z(0%)ffGF-dEXfNL8c-2O3j7xJ<+~9k+-f|r5Jwhdn)lAnRZ!*rA+_@<$yHj~KBfU- z7d_Fk>!^p5HggWYjTkF=2bMohw4%)@FY#CgA-mB&>!YT0;F$!uRd~@jcB<{i9=JP=Nr84*Ud+3mtXi zKn0rKINHxodw~Net~Vo}fvhA9$it^ip7xeQG#o(mp8=vMe_wwCD2V+V{Vu)k8dPD4 zdmS_%&-)X?CK|kjN&#sIWXYLeCqT=I9+HbtyR;Mkn0tOCZ=|b>^q-wjX~|r>k&?$q znfYFbr!~DpA0ItPn#Vx0DLyit=IpUXvj5{dniwPQm8ZHj=kP~O^BV=jQX7Eky1NK=4g!{oJe}9OugF-2gRwW(y zw1=>PNCoPm4xlt{{kS{vnF%Op^K)VaLG#1hwv_EAw;|<`Vet-p0c!q>Jan5Y=LmeL zv(K+{8T^fk-Mzsj*whAfFa2i`;8Uk&wy1V)OP*k)hPW%S5k+Rtn-^cRB2s1#?C?$o zW_p`q{ru&~as-?Ra%CT^?{F^IJqWyWSP5t{3@b)udwPm@%i~|oj!+oN zv49Q*pc2tw0LaGP>k~%n7eA(c^ym@eYUr~!APCgC+t~wj)8KXZLcGakSpgEJOo}=z z;y7I4mt3(&5+g_p5LO%)@^u8`$eu~OpoF0GQ=hp|N&5QDBqbE?DO(7yE;rwe#P7n| zQg+=Gvj%6X)+bDl0;VdM<<4IYOjpaue&ZKFA|*{i2olc+3$qAlp6}PT(efr_6P)c4GnWC$#u>CA1i$84~N%%)G#bq+3`F8C#-rzQ;y0 z9?LOimxpXfSC~?MR&3!LWcNK(SRin^O9(9{|zc`5`N`%JOIh?Km= znx;z!)gH8o#Mj0ccg7at^v>n50yng-voIyMMA+L>a@vA2IJPA$A4aJkx{9a&G-K9S zsQg%C@`V26>)AOF6_8_UOMOQ#42XRzku!?Eojmg%*lL=AI()E^tLms^U?6X#_ySu% z3)YB3uU0Dk36-hsNmG}&D<5}LGW*p&&H8{ExI1I5oWv7Aafgl;=>l)18Ibk6=F+do zi734*WWfb{mzcQlgEhS!jAcZCC1ryd0w5u52GWDH63x{HWUyKB^AFk>(e%$wDwE(* z#u(AJFN(Lm5YRDWO|3n-kHtcDLEXQC_n<1|?&!_j$Rr(9lmHuB6%H0UYuL-jr;J7n zYA=jTve*C|qo1ml&wzIJZB}D-WawCH@@5B)|B6JS?ntIN?}OiuPd$DG=}nfx5sxJ&%`p7?eH+j4CZIDG{?j zU&|-IWH~rXlO7QL!h}^<7)!s*m{zT-X(~D0?iT$mU;0IYZB-a{c&~i9h zivr%ovzugWbcUN$UZ-EqS=s3~$^Gg+e)By?M@y>87Qe&+_rxG6BU2`%%&>VJ2UUYW zln8|D_*HR~$y)yOT_0Ssrk=28^-9uNG~IQqA`oz@kFq4?y*e9jdiLWrGvC@VmlZ%- zcNM zg`~)Ch|Ao4b69sc_&Gh`)-N~8mfp#F0+@`H685K52HpctI}`RoGp-qO#+*kNDUEy1!JVA7sR*< zhzt$5;ckF^WS3izWIXbSoY{-16eG1bM{LJyWJ<4V|C%#o|yLA>C_sQ#6#Zf- zSoNwfuQ4R+1ti`7=>59|kZXfLV4K&NmIk6ESorfS9e6JhTS?xC5(BT!Ld6pzR*zgN zbfd2CZ3}B;T<8W{hYGlXW9Q3w?ouxT2Ttq0mSIhH5+LJWYJPq|)QacB*P8D8m>iX& zasif)eut=@XZ*|HwGDAZtRbPpSgeOiZ2CQU%HXbB2zJGF{KI(d2N{ndNK_DBu2{2Z zN~3pkI8klEfO)SvNdvgDqoMnSp9JisOx@^pDvt^pOaUAXh>hh8aoS1k5DlizA8{k65f@QYtdpbJgyJ z{;!Pa2X$VdV88hn!gRD9kW%an7Ot)XAqXXSCMRmccw`IlASWP?b09a!Y^ew91=cZLH zvI&K+_GApJ>B%0TIA9jC!F)C$1rZNbWKF#V#ZoZK1ULfYnFF*;FW$2( zyrC6N2Bp8bg@_^ffRnkNAe)gTyB_Inin-wU+8qZUS!eG3O(xlbZA7*& zsoR@}thq?|3=`+ruGE_-0nMn&&o?vsZQ%Fp4<&K@C)Z(HJg>mMl4~etc-;_#)oY|^ zH*wPcxEFUYHWQ_?ji~Yi;ZWiK=g*)2?XEZ5DN9mEQ50VIQtkA~)vosi z?S6g6l*129L28-(k`q2_pX78!B4t#f#GG4C8{9)>))cKxWH=8jU(^BWy6~LvOY&P$ z-6lC?n5bQojVq;sr&025$YF87UgIWgVP6*W;>Y}L^_%F0ubQ*BP=!oewx(E+%nLA>(SW_rwC?|?;wvJ;`uDI8*8p9TjH254JVwpKo&6vRH$uYddDG}_}=r6C(cfzvsJ z`h+op1OdO-q$jO{>uFM4j@FB%`#H$0eP0wa8d-7vETzmd-T+IByg6IOD-jj2R)6Cg z$%e=5sloUDJTgYg-#t6Il|gsYx?F^aIb&rC_pVY@T94LE!3om@8hy)nL_@1`!$KLW zfvgquz;M1RWp7o61WQ4^&b&rs+PlB8$Vv`BJVC~k;eOL<78V0hBvv0emYm~UwH#L1 z&?6-O3s|&BZ)Ejm)PDVsP$|v}Pi-l6jiRLxEmYb#so*d67T*ukO2k7qery}t3SpRMd;w=^a_~(ewvyMW`Rfh}P@8z&MKy4*M`si~t`en~vGZVI0r4==h) z)RA%d2Um-IanK!Wvb#9XlYSC0W3jolwTOEvlr`~`z49hZ-%G`?wYNF5ER36PY+{ke zUjIIq2VDmdCJh78z&2?5$^@lE3!JnqQBG2U4-;7PqiS8fov5=W^$GpF$8#BvD1zuJ zM-dy>Yt?M0Y$rZ199ihuxfV`+Q0!2AX-FeJ^;~`KUf55+ToKC>r}B^oup2 zmQff7^CL@6EPc#|;)J!&cLO+#MW5T*x%}j+S%9>TfP!c>9*^|7A6OiV$m@xiB%7(F zcxLkCS5nMch{hdl>04<`10OjD*xiDx&GRR^1XAC$Au+qyu060l;ETzf9k*A!7u0to z{B=%-8#r>hL}2YMzuB}K%1zhtycl0NM_0vZm5isU^hVC!v_vZRehWe@4k>XMLl$MtCfQVTY?S=&DIp^@zT<4Tn;IVouotQDbDN^Xk z_v=ks@}Vubmf7)nWox?D+mY6f*@bKNbNIfhg|TaGh5jvZNATh(B2gH*2Bn~`cT~KU z88CY0v#ZPI*bizsv9HfMx6r>!1T;g_zhYp@lJdU&Uzs1IyIP<9CggRn9=P_=n*gX) z%rs4&y?F-fk&mJI{VakQWVd^bFNM%3RQAj5TG!h}I79g}jc9Jmd(vU_5V4^n$IVMM z?*?7MOHiQZFSH^bV4@etaf^FK$0m@&Om>v^wh_JcBRNOz^2DkNEWQP0Tk_>ur({PO zBa2(9RC528gh{zShdSxd@$QX6xA6O1DQ6my-5}-K^E`ZNZ0r~(F1*)H>H?-ig;sJ` zkcbPFG^W=V9i$}>1y^5AUaYXVE2#vJSfbK2UIC(=psRY~{LYC_AJHQ(!YFrtY_XiY z+$$_lF0a~kx+`Tz1-L#GUfZN8m8K1_>uYjrOCQZiRXQPEb)hz4a(i0z%i7Ue@Zq;r zMS*h!6{$Yw;0@Ik;#^PH0#Lt{6ewK{)>U7sJrX|4__Tq4h^4h-Q%~BBC-(XPF!oDX zQQR_Mh;pD<{~lDa1I9k;Yd_TC%#M?w0;CDF&!AvUzKF;cMm3{-1~bF3X0tGwPzn^>PS>`~IeEBgzq$R@}r(R7i^-ga(x618=Qae)(n6ADJOsF(}d$rq%&6*Yf_=jbP zJOZjC6i7|b9E|$$B;a6xggmCGv5td3MUer<#0=19je zsYba$8F7(KE^4HhxH^|s+>OPFx`V>KpV0Qn%GJ>vl5y;NMB^lPncvmS57lBTAzDYv z>B6&L9pQ^S{X_;6s5JR7NjLC4G?qo*^`YouAxY@LN-$oic(1-lRq5@cXV|~hY>JBt zPhwE{XVIwq`$%MyR}=9S6%`KWMfG!x!8}Aoz5I#I?m$E>SLR!zt}l=FHO$cu`@dz5 zk6Lb3d)iaeG2Qum8^B#~L0ZY&dRH<+n;8}%%cAZA-Y(4uHb^zcN z8!k`5s2B=Ny+dL?$d1kqw~~(b_Kn663m^{iI?f0~q?rts5762`#`U+O4>tZtC~f97 zb|5zGz@>XVyH&iNtD7D<@2~3GwQh2qlc;;L{yhs+Ug<;B#RGZ_1GlcU$jc=RfRxh} zE()kkBp&u=0P%MjSz{$ObRxVE9p}oU>N$QpHzy_Ds?<0%hBAGXMiRB#ceI+2OT)ck zx2~uzi16XfYxl-5?zg2I>!u%%+EiyDva-l6JaKJGy6LqS{UqUv6RtjVu;a9-qpbjg z-9TL|wnD_kLFFK849-)gI0W>mB(Y#(ZwUR1MEegSnEdxwCP@F01#D0ha$rPvpy};xOa42%HnYEV}wJyuNV1gL4nev(H zMOy1ih6f>%Yc{Phpvm3%^ni#`mmAp@k4k!h!E0|x&_R7Ug9VVVTD?MUf8j|7zWIb;8pk5G0@Dx);kZz_2JOEW?^G zdu`4fuqZ+8b}=d>b#@u=emJmo`;X*BwWC8=la&0e3$BKM=Q@Tv$GxXt!>`3))sNxG z0E*R`BWnx;6_v5wuoSgW!~!%I_$2AwyR51z0sDRb>+^Y!?ay7%a-e4A2~gcT&$^Fi z=H%Sjta1ipfS{gt6W7((j{tRiR%s~#;7OHF|F|1TKi>chQnjR zl7yrib>^4LnK;=R?{YTozN z#LK$US#MfSIO7GM9m?O-Yr;xW@)6xCk|F6!@J09!*|M&0f za@l)jCL?832#LaFMJg*R*&?GsCg~(-u?4qQUl`S*boaf8udw%Ep zJ->6#ALn!Xd~Tm)y~peId_Cv=kz+!6K>`}GTwxHv*JD#XvOGT-=9=2iFa*^Yj(f_l zNkp94I5AJUNW#>0b$lWhBQ;j#27$R z<@9G|VddsPVS&ollN%l(s+Ad(#q&nXXMOu6%?2*p8Jh%47IN;v_&n4tV;4ij6K300%^+F;q;pN5ehq~{%d<-A~x`IcW-y>wQ42_#?&1`K{<&KVZ zJ!MC8n(ZbqrwIdo&nNm|k<5XK-5&f`@hhDyfduma3@^QZ)vj`fmVHl_U$lB`3Fhby>3Ixop+=cH8yc%uGjmLpS7Fh zmo2jh;Dd^5bz5ei}Y8OjuH2b8|Dhh3rxYyB^uh#(&s% z8hRC@dqywK_E)22VcGs11_hvBS8vmI=VQ|5b+p%5U)760Nx6v{yU`IwVf&hC9cCv6 zpkDSKqQm}$6?fP}L-3?(!GDQ_Rj2^l=Wq{0P~ttEzOoeO%_#Owdn#qYD_=b+MHf7+ zcw1l4FhkSO$ERTzOhRY5Pgj_qt}K-xrHcgI=j^~nbvAUCMj1T5c#B70)KH-teJymV zv4Adff%}VxKQ4R~3u&hbm`!|8rA|WwKJbFJ1@63A~P_je(}4~ z?)B^aZcoWGG^C)Bz)NkZ+*49K41x9GOgu)5_pge{Q4L|f!T3ztud9y}RA(|6tUu@C zeM4@N3#_8HoD8nY&5QLr#3=7TeGV{N9Cl--k_(;TklC_qeh&1FodBFEsha-$jO*e4 zvth8l1W+dc4DW9bo+wkcz#`#4R9g2GM!eo$TVQ^i-$r3>Xc&a1WRstW@kX)XI~hre zrisO(yqori7LPIer5DoX#&!tbB6>!X&uOI1`a~6R@opX+Nn@5=KVx!ADALth!mD*B zJ~Pz%Z3Nf+J4K05;laNjpG6FC5>*ZQY>hV|-#4$kE}rdZU=ja)pxwrrjwH#s`B1`d zKLNi#vVZh4&Uycz{wB#9UO@`&&~_iauj%^VQt5?S^YTJW^Mun9R3)9p4z2F+6{Iu} zZehu#Aq1={R;?McVR9cV$cRSJrZkzKTc~X@>;Qwvz$kK<-+M=`Q_jc!Pq3*8XAn^^ zbF@VpNCv5X^T%txUtz0fX#691f1k_Ck-k{gcLlRgEDE7-Fd|55Uxf~B`Z3xdBVL@$ zZ5D25M`c$|Rx?Q2*b2EMAe+b{)+#zA*J`eE;GQ#ujc_G1af-Ez^=78~y916zJ>4lo z`c&(;f1c925~lh*LlOU6xBqf>O?MOb?7(Fv5$rXF-|scnDo^v-@FV*thO5=?dqYAp z654SF96R%b)5VlRFk>xkt6(ng3=W*nzu5 zv+A<7^W8q?(Y3*K?&J9^<9>R&WSIt=pSP-&zzk?svZg~TZk9TqBq&< zJ+@!YCy6>O*H`+F5ch0;{}Tx%W1)1KAy1**N7ZkceeO5(5{vz6W)xwC|0)$2I2g)7 zmtTFz$goAiL0q>5%ca9z?4GV5wcoK2QNWGf)697!{ud`m45LUZ89S(WuJq|4`_t~H z?|6_-8Eu@9S%1&y*A_#RZVUyB#qt1*LzHcjc=Iw#sXsw2ewI*x0SmDlmr1QPb zvyNWl)0)0d3?!#ndO4^iUU*vF*&DN?m9Kx%*+B5O>*Kt!V_(^ojz+Aow8ijpND?G? zkE++cBl2+QOtG<*sHg~nnm-zP!Q!;E z&-TbF#_PllnHwotOH?2F{-DNrpj}2<$Q63q{%ASlqj~Y1?{neKf}&^lTCyuk&ef(i zGG3b zH~CBK@O~%)UkXu86;EbR(qEN(n}alOi`m>IGSIvuE@00`F;Vt`_{bt~yvQ#_2&B z%XYs+O%S2C934eb=TY|p%&;^7GYVx?&P{e{2_+5>vME0no%Zm2UZ$W~*Oa=EG{|(} z?SpQ9}u)JP^NMP!KN>7uaKEEOBgD zdr957HEkkLSai2!kR~OhOJ`vmt>K>%GqeRCfH_s596BCc*ZL+kF?XMVBpziQ{YuWN z!sJBOfvAtK%jHJ;JX7>1eBC!y$IaJI##gh9PSs9KX+IIGcWcv4WvSO56*XT=9%xs2 zx0qDGHz1W&nBV2-{+K8k=#s><+A`ELdOxtEb^J`rYXK{66RlIc>7DB|KaN%{_(e>t zR@s2BQm44r{Yx>!RT-V5jkG4A(nl^gm#_AYjl>H77!7uwRg;q=%K4 zA#`luYnW*mSpskaTpbh=cpT>ZpPP`F8`a!Qj9R0JAFr7DU?Zd#NZ zW`Ew@e_!+~HBr}2VNHqJCs)_mvuHYxLqh$U2_0!pp@Fm%?{NO&iK*}13_-k7UA&w> z{qaBj1K)h{sC2~Rs_>tsSZA*fEXJ!XpT)2^UTMMzty{m3(%NaeW(#Zz!hBRw|1?2)_Be%m?Bi2JgcLnslP9dSwdJW{skG#9-P!Id}UK)NoEk(FWO9$x@_#M0r7 z$a{k-%L6lbMf{$-Smn1rze~>JVKRA@n#OYQf_tO2jd(!b#h@f!+4bM22cFY1lO7Ti z0|(90mX8|viOw!3CDPv(Bc9s7MquL%1Se0ju!0RRMM1!c19usZA$kiM9qx6nWrXgB zYI=I-wzPX>sd00Y>VyHQ+KtT&6Ut5|Qd>9VV#XY}cHp1m_}ZK-wYWKtoG=$GZW9u@ zr3Q{*k~PGi(Ko`)X^Y!%+|N`Jw)oCMg1%>+PikH93}pI=Jg-!Rc=r;%4HTZ?>0iW) z9>a>&Z!uxlRRlGkJq^m3G{_3cqfpnSsjM6GJm30vpIrb44cURA|7yz;SIVy*?!#FL zHb*Ejti+AIZ~Squ>2x1zNSWF*6{W%m9ERcd)9q&=d-HtagWIGsWf!3!#&i^z@K?!;ih6XGeSW z#I90yaN=R)L`J(=m>Z9KrT@tD*X2m!7(;N|=_h=f{7d}|L03EC>YeRpL#cnWisCNpg-%9EcDODMhLz z9cAuKx&4RxMS5mOOQ|IZye33dLPabMp;pp%Hz8*4VLHVJYD9J1(P|gZshLZHw#Il_ ze*A-bY~i0i*)B^;hVGlgTYGA;lLb;lIP5GngrG#)s+*>$Yx$6GU9Yb>x<|B@1Dc@&dah%7P7PF9dc??J*za;(=xt#E@`E#wVx4U z=&7Gpr8#$KU2$5Cs)h3y3me|*a|3a;b@7Xw?4BF$G%dQ8-pzQ^2m5ck+SYAkyxW&z^L13`2*F8dJ#?qp zZGJqbU0d_$4tWmzbkHt~#zmO7I%Mqibze!@LiBJsM-(s694@7WN8jO>9!<5~*L-QT*Vm2pGs!s;;1N@G5GYWPJ*41Vv|W;o&3J zU(a{2i4f=#&Pbbc7e5Oua827Nai=DVC~C}6{7m{)lPYSkCvEk&OiOId`ulV;(=SZJ zR?j{>lN)v+X?;!`hM2bypa+e|^ZWD%A>^YBaF-DN5C!AM2x?Pnzt_2VsypdHqMOi)zwUlFTuvBJb-2iy}jkPu`_6hV7g*KFU6ytr*wV3 zS;nb_TWs#jj_kCPAGFOxm`q zSKa)eQGEGNr#^a_fTo~ATN653d4~?p>t#H6okd|*>}q?!Wb@?)y=J*&;NMT@)0a5s z{G-@ecBTVe!f_yAibc#sByQYQI)(PtqXTzY#td;Wt|6+0uKOg<3ur4*-%PM%Si>zfbAwvKI|Px46-e2sMqsSPNz z%tDQ$1f7}p(Gny{hZf>1LwYzaS)C|maSp9=a%8bC{5Un4yFM=Z7;LIZ+V#*(d@ebG zODmKka6!+~pQ2U5?sZO{3xiQ7%kp&vk1!D7}82%n&NpPzQkHBt&EsvOsrq& zwvm+I<(S^uR+DmR&(}Rtp@FV2xHd}1f%iRi(K_bK9*J}CD0UvXS_icbX`k8t-0uh# z4am9=UqpXB*TkFUHyPLGI2@m~5T4?wqD!EMQFrTSQntCq$867+SJ~X$8#=8pGI2j3 zQ$KBITZr_-8=mvNg37MHV8|BpbYgp!v}R9r{YTz@z0F~J5CbT=#|=S=m<^N4~C#N%sHiDHKy#<&=&g< z!nX&+F!G-2f1N+$Pg0}bMzP?b54jO;GCQl*CT`PjJiqO3O9@7^Ig~n9c13($u|3s` zQo8;{(oI=Hl0K~#w`3@d-AOjakXx#SbWbhR42TNaEPPv^(>3JH2Bl-hkDk||WWqGb zmQL_G9UVuErG!NMPnbB1(q)+inF^;pAV5vZ-UQPyb$p?OeWM`uj=o9CiYmiTCU1^P zFn*J&C$r?vZOyXX-P|gEdrORku~mpyH@z#K=r$entzRuI5&!wT96fbY$i^P3mb_F` zCrHd2^A4PqIi0p5beJoh?ShnCbG_*UQ*v%oQ_{Bzf#;86fR2vfbOlhJ>$db{gyA6n zxcKj2TJEQL@+;my)uq+a zWZ0kRx*6s3SZ9gVapIx#>GE@;>xzZXSZ-QAzF$t@z4?miY_M*~O68lXvwtJJBQigT ze_b$G#O3L$&z;B(pv_jhHQ1T9>@CKKqp`smrjurcgr(=`{{4c zD#}b52_0vSv&wI(sOt@c-)2bQAP}}$#JN_kNUJV&o$#6P^5NaxwZYp}j&*IQge&bT zs$zP1RW&&QF6UELBYco+-KbK)bEvWV zllegVYEspDa!Qw6WBF?TR|0vAj|MYRQcqiywPQN)vGutq1kz$S+7h_<_+!fp;|5U4 z41iPxBO@`G`DHbAPX~FH>vmWA=Purj1+SgLzc#qOgtNFg7p{D?=s!m1z{y(jbNy>S z4ar-n3mT&~|0-}p#IUp0=CnPQb@-qPy(b*j6+g!o7@#nTkc3Yi-fjH-&MoW2Q0_I3 z7a}}7V8!dXhA2bO-@Knm@fQn>K8T;r(d?au!gvkp6M#u+RH_1KfrU}`gE)==AyKx6 zSqFY=>vsS0+wHFW_qy&IngmWAq4;O@dmC^ks*CR zLzG)imm{?13XhqX)C1DZy`tta!+A= z%wxK2bP(!LQP+RFG#k;JT;CC&eBK!ArQ2VEbxyln0t1tKG+X%*5mL4CDx5tlq$TNyuF~3+mJL>b(eDD<2 z8wW9GUnd&l{8XL=m-C)QKNx5~Z$5q+@Pp~ru~~ZJ@;WS7R1{hbtFWfb5+7SzqL5z2 z(_tO0XLdZND>Syv*J3d5+yDN&36*FU6t^~TxrB_QLM+~oqI0+{#KHpV&RCE$b0*c|iQ046L5mt)Yl5zPf#piD@TT&Fhp7gZMI=9iz=xxw z@EDqUD(SYa1#;XRJZN>@+c3k$4O4|5>c@Fo!2`B5sYMljq-qeblQlVnZ%a5bh86F8 z8ek718n)A&d=u#jee`eHoU3TWK3V>Ku7WMghf~=U^}K=0Gq1r>@uVwsQQWXoXg_

2SMD!>(Ezr!)RypR_-00zXDyQQVSTKkg~< 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 SJNN>Fe~xSEX%?v4-uxe~0j;(G literal 0 HcmV?d00001 diff --git a/qats/fatigue/sn.py b/qats/fatigue/sn.py index 859c2a8f..13e65ba9 100644 --- a/qats/fatigue/sn.py +++ b/qats/fatigue/sn.py @@ -25,7 +25,7 @@ class SNCurve(object): unit: str, optional Unit of measure for the stress ranges e.g. MPa b1: str, optional - Mean stress coefficient in equation to calculate the intercept parameter + Mean load coefficient in equation to calculate the intercept parameter b2: float, optional Corrosion grade coefficient in equation to calculate the intercept parameter default_g1: float, optional