예제 #1
0
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.

    Parameters
    ----------
    fatigue_life: float
        Fatigue life [years].
    h: float
        Weibull shape parameter (in 2-parameter distribution).
    v0: float,
        Cycle rate [1/s].
    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'.
    method: str, optional
        Which root finding function to use. 'brentq': scipy.optimize.brentq, 'brenth': scipy.optimize.brenth

    Returns
    -------
    float
        Corresponding Weibull scale parameter.

    Notes
    -----
    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
    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``.

    See Also
    --------
    q_calc_single_slope
    """
    rootfuncs = {
        '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()]))

    if type(sn) not in (dict, OrderedDict, defaultdict, SNCurve):
        raise ValueError("`sn` must be dict-like or SNCurve instance")

    if not isinstance(sn, SNCurve):
        sn = SNCurve("", **sn)

    # fatigue life in seconds
    td = 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)

    return q
예제 #2
0
 def test_minersum_weibull_scf(self):
     """
     Test that SCF is correctly accounted for when fatigue damage is calculated from Weibull stress range
     distribution.
     """
     sn = self.sn_studless
     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,
                            msg="SCF not correctly accounting for by minersum_weibull()")
예제 #3
0
    def test_minersum_weibull_singleslope(self):
        """
        Test that correct fatigue Miner sum is calculated from Weibull stress range distribution.

        The test is performed as follows, for three different values of Weibull shape parameter:
            1. For each shape parameter; calculate scale parameter (q) of the equivalent Weibull distribution (i.e.
                Weib. dist. that gives specified fatigue life)
            2. Calculate fatigue damage (for one year) using specified shape parameter and calculated scale parameter.
            3. Compare calculated fatigue damage to fatigue life (damage) specified initially.
        """
        sn = self.sn_studless
        life = 100.
        dyear = 1 / life
        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,
                                   msg=f"Wrong fatigue life from minersum_weibull() for linear S-N curve and shape={h}")