Esempio n. 1
0
 def __init__(self, *args, **kwargs):
     # parse parameters correctly
     param = parseParameters(args, kwargs)
     # set default parameters
     self.name = 'NakaRushton Distribution'
     self.param = {
         'sigma': 1.0,
         'kappa': 2.0,
         's': 1.0,
         'n': 2.0,
         'p': 2.0,
         'gamma': 2.0,
         'delta': 0.0
     }
     if param != None:
         for k in param.keys():
             self.param[k] = float(param[k])
     if param is None or 's' not in param.keys():
         self.param['s'] = .5 * (gammafunc(1.0 / self.param['p']) /
                                 gammafunc(3.0 / self.param['p']))**(
                                     self.param['p'] / 2.0)
     if self.param['delta'] == 0.0:
         self.primary = [
             'sigma'
         ]  # gamma would also be possible here, but stays out for backwards compatibility reasons
     else:
         self.primary = ['sigma', 'kappa', 'gamma', 'delta']
    def dldtheta(self,dat):
        """
        Evaluates the gradient of the Gamma function with respect to the primary parameters.

        :param dat: Data on which the gradient should be evaluated.
        :type dat: DataModule.Data
        :returns:   The gradient
        :rtype:     numpy.array
        """
        
        m = dat.numex()
        grad = zeros((len(self.primary),m))
        s = self.param['s']
        p = self.param['p']
        u = array([self.param['a'],self.param['b']])
        cab = .5 + 0.5*sign(u)*gammainc(1/p,abs(u)**p /s)
        for ind,key in enumerate(self.primary):
            if key == 's':
                U = -.5*sign(u)*(abs(u) *exp(-abs(u)**p/s))/(s**(1/p+1)*gammafunc(1/p))
                grad[ind,:] = -1.0/p/s + abs(squeeze(dat.X))**p/s**2 - (U[1]-U[0])/(cab[1]-cab[0])
            if key == 'p':
                f = lambda x: 1/x
                df = lambda x: -1/x**2
                g = lambda x,k: abs(u[k])**x/s
                dg = lambda x,k: abs(u[k])**x*log(abs(u[k]))/s
                dIncGamma = array([totalDerivativeOfIncGamma(p,f,lambda v: g(v,0),df,lambda v: dg(v,0)),\
                                   totalDerivativeOfIncGamma(p,f,lambda v: g(v,1),df,lambda v: dg(v,1))])

                U = .5*sign(u) * (dIncGamma/float(gammafunc(1/p)) + gammainc(1/p,abs(u)**p/s)*digamma(1/p)/p**2)
                grad[ind,:] = 1/p + 1/p**2*log(s) + digamma(1/p)*1/p**2 - abs(squeeze(dat.X))**p*log(abs(squeeze(dat.X)))/s - (U[1]-U[0])/(cab[1]-cab[0])

                
        return grad
def pmu(mu, params):
    mu0 = params[0]
    lamb = params[1]
    alpha = params[2]
    beta = params[3]

    return (lamb / (2 * np.pi))**0.5 * beta**alpha * gammafunc(
        alpha + 0.5) / gammafunc(alpha) * (beta + 0.5 * lamb *
                                           (mu - mu0)**2)**(-(alpha + 0.5))
Esempio n. 4
0
 def __init__(self, *args,**kwargs):
     # parse parameters correctly
     param = parseParameters(args,kwargs)
     # set default parameters
     self.name = 'NakaRushton Distribution'
     self.param = {'sigma':1.0,'kappa':2.0,'s':1.0,'n':2.0,'p':2.0,'gamma':2.0,'delta':0.0}
     if param != None:
         for k in param.keys():
             self.param[k] = float(param[k])
     if param is None or 's' not in param.keys():
         self.param['s'] = .5*(gammafunc(1.0/self.param['p'])/gammafunc(3.0/self.param['p']))**(self.param['p']/2.0)
     if self.param['delta'] == 0.0:
         self.primary = ['sigma'] # gamma would also be possible here, but stays out for backwards compatibility reasons
     else:
         self.primary = ['sigma','kappa','gamma','delta']
def gs_val_meso(gs, t, ca, k1_interp, k2_interp, cp_interp, psi_lcrit_interp,
                psi_x, VPDinterp, psi_63, w_exp, Kmax, psi_sat, gamma, b, d_r,
                z_r, RAI, lai, lam):

    psi_crit = psi_lcrit_interp(psi_x)
    VPD = VPDinterp(t)
    k1 = k1_interp(t)
    k2 = k2_interp(t)
    cp = cp_interp(t)
    x = (psi_x / psi_sat)**-(1 / b)

    psi_r = 1.6 * gs * VPD / gSR_val(x, gamma, b, d_r, z_r, RAI, lai) + psi_x
    # res = root(lambda psi_l: 1.6 * gs * VPD - Kmax * (psi_63 / w_exp) *
    #                    (gammaincc(1 / w_exp, (psi_r / psi_63) ** w_exp) - gammaincc(1 / w_exp, (psi_l / psi_63) ** w_exp)),
    #      psi_r + 0.1, method='hybr')
    # psi_l = res.get('x')
    psi_l_temp = gammainccinv(
        1 / w_exp,
        -1.6 * gs * VPD * w_exp / (gammafunc(1 / w_exp) * Kmax * psi_63) +
        gammaincc(1 / w_exp, (psi_r / psi_63)**w_exp))

    psi_l = psi_63 * psi_l_temp**(1 / w_exp)

    phi = 1 - psi_l / psi_crit

    part1 = dAdgs(t, gs, ca, k1_interp, k2_interp, cp_interp, phi)
    part2 = dAdB(t, gs, ca, k1_interp, k2_interp, cp_interp, phi) *\
            dB_dgs(cp, k2, psi_l, psi_crit, psi_x, psi_r, VPD, psi_63, w_exp, Kmax, psi_sat,
             gamma, b, d_r, z_r, RAI, lai)

    B = (cp + k2) / phi

    return part1 + part2 - 1.6 * lam * VPD * np.sqrt(
        (B + ca - cp)**2 * gs**2 + 2 * (B - ca + cp) * gs * k1 + k1**2)
    def dldtheta(self, dat):
        """
        Evaluates the gradient of the Gamma function with respect to the primary parameters.

        :param dat: Data on which the gradient should be evaluated.
        :type dat: DataModule.Data
        :returns:   The gradient
        :rtype:     numpy.array
        """

        m = dat.numex()
        grad = zeros((len(self.primary), m))
        s = self.param['s']
        p = self.param['p']
        u = array([self.param['a'], self.param['b']])
        cab = .5 + 0.5 * sign(u) * gammainc(1 / p, abs(u)**p / s)
        for ind, key in enumerate(self.primary):
            if key == 's':
                U = -.5 * sign(u) * (abs(u) * exp(-abs(u)**p / s)) / (
                    s**(1 / p + 1) * gammafunc(1 / p))
                grad[ind, :] = -1.0 / p / s + abs(squeeze(
                    dat.X))**p / s**2 - (U[1] - U[0]) / (cab[1] - cab[0])
            if key == 'p':
                f = lambda x: 1 / x
                df = lambda x: -1 / x**2
                g = lambda x, k: abs(u[k])**x / s
                dg = lambda x, k: abs(u[k])**x * log(abs(u[k])) / s
                dIncGamma = array([totalDerivativeOfIncGamma(p,f,lambda v: g(v,0),df,lambda v: dg(v,0)),\
                                   totalDerivativeOfIncGamma(p,f,lambda v: g(v,1),df,lambda v: dg(v,1))])

                U = .5 * sign(u) * (
                    dIncGamma / float(gammafunc(1 / p)) +
                    gammainc(1 / p,
                             abs(u)**p / s) * digamma(1 / p) / p**2)
                grad[ind, :] = 1 / p + 1 / p**2 * log(s) + digamma(
                    1 / p) * 1 / p**2 - abs(squeeze(dat.X))**p * log(
                        abs(squeeze(
                            dat.X))) / s - (U[1] - U[0]) / (cab[1] - cab[0])

        return grad
Esempio n. 7
0
def totalDerivativeOfIncGamma(x, a, b, da, db):
    """
    Computes the total derivative for the (non-normalized) incomplete gamma function, i.e.

    d/dx gamma(a(x))*gammainc(a(x),b(x))

    :param x: Positions where the function is to be computed.
    :type x: numpy.ndarray
    :param a: function handle for a
    :type a: python function
    :param b: function handle for b
    :type b: python function
    :param da: function handle for da/dx
    :type da: python function
    :param db: function handle for db/dx
    :type db: python function
    :returns: derivative values
    :rtype:   numpy.ndarray

    """
    return digamma(a(x))*gammafunc(a(x))*da(x) + exp(-b(x))*b(x)**(a(x)-1)*db(x) \
     - (meijerg([[],[1,1],],[[0,0,a(x)],[]],b(x)) + log(b(x))*gammaincc(a(x),b(x))*gammafunc(a(x)))  * da(x)
def psil_crit_val(psi_l,
                  psi_x,
                  psi_sat,
                  gamma,
                  b,
                  d_r,
                  z_r,
                  RAI,
                  lai,
                  Kmax,
                  psi_63,
                  w_exp,
                  frac=0.05):
    import warnings
    x = (psi_x / psi_sat)**(-1 / b)
    soil_root = gSR_val(x, gamma, b, d_r, z_r, RAI, lai)
    #     with warnings.catch_warnings():
    #         warnings.filterwarnings('error', category=RuntimeWarning)
    #         try:
    #             res_psir = root(lambda psi_r: Kmax * psi_63 * gammafunc(1 / w_exp) / w_exp *
    #                                   (gammaincc(1 / w_exp, (psi_r / psi_63) ** w_exp) -
    #                                    gammaincc(1 / w_exp, (psi_l / psi_63) ** w_exp)) -
    #                                   soil_root * (psi_r - psi_x),
    #                     (psi_l + psi_x) / 2,
    #                method='hybr')
    #             psi_r = res_psir.get('x')
    #         except RuntimeWarning:
    #             import pdb; pdb.set_trace()
    #             import sys
    #             sys.exit()
    res_psir = root(
        lambda psi_r: Kmax * psi_63 * gammafunc(1 / w_exp) / w_exp *
        (gammaincc(1 / w_exp, (psi_r / psi_63)**w_exp) - gammaincc(
            1 / w_exp, (psi_l / psi_63)**w_exp)) - soil_root * (psi_r - psi_x),
        (psi_l + psi_x) / 2,
        method='hybr')
    psi_r = res_psir.get('x')
    print('psil_crit_val status:' + res_psir.message)
    X_part1 = grl_val(psi_r, psi_63, w_exp, Kmax) + soil_root
    X_part2 = grl_val(psi_x, psi_63, w_exp, Kmax) + soil_root

    X = frac * grl_val(psi_x, psi_63, w_exp, Kmax) / Kmax * X_part1 / X_part2

    #     import pdb; pdb.set_trace()
    return psi_l - psi_63 * (-np.log(X))**(1 / w_exp)
def plant_cond_integral(psi_l, psi_r, psi_63, w_exp, Kmax, reversible=0):
    """

    :param psi_r: root water potential in MPa
    :param psi_l: leaf water potential in MPa
    :param psi_63: Weibull parameter in MPa
    :param w_exp: Weibull exponent
    :param Kmax: Saturated plant LEAF area-average conductance in mol/m2/MPa/d
    :return: Unsaturated plant LEAF area-average conductance in mol/m2/MPa/d
    """
    cond_pot = gammafunc(1 / w_exp) * Kmax * psi_63 / w_exp *\
               (gammaincc(1 / w_exp, (psi_r / psi_63) ** w_exp) -
                gammaincc(1 / w_exp, (psi_l / psi_63) ** w_exp))

    if reversible:
        return cond_pot
    else:

        cond_pot = np.minimum.accumulate(cond_pot)

        return cond_pot
def gs_val_profit(gs, t, ca, k1_interp, k2_interp, cp_interp, trans_max_interp,
                  k_max_interp, k_crit_interp, psi_x, VPDinterp, psi_63, w_exp,
                  Kmax, psi_sat, gamma, b, d_r, z_r, RAI, lai):

    trans_max = trans_max_interp(psi_x)
    k_max = k_max_interp(psi_x)
    k_crit = k_crit_interp(psi_x)
    VPD = VPDinterp(t)
    k1 = k1_interp(t)
    k2 = k2_interp(t)
    cp = cp_interp(t)
    a = 1.6
    x = (psi_x / psi_sat)**-(1 / b)

    psi_r = a * gs * VPD / gSR_val(x, gamma, b, d_r, z_r, RAI, lai) + psi_x

    psi_l_temp = gammainccinv(
        1 / w_exp,
        -1.6 * gs * VPD * w_exp / (gammafunc(1 / w_exp) * Kmax * psi_63) +
        gammaincc(1 / w_exp, (psi_r / psi_63)**w_exp))

    psi_l = psi_63 * psi_l_temp**(1 / w_exp)
    grl_psil = grl_val(psi_l, psi_63, w_exp, Kmax)
    grl_psir = grl_val(psi_r, psi_63, w_exp, Kmax)
    gSR = gSR_val(x, gamma, b, d_r, z_r, RAI, lai)
    dEdpsil = grl_psil * gSR / (grl_psir + gSR)
    gs_max = trans_max / a / VPD
    Amax = A_here(gs_max, ca, k1, k2, cp)

    d2Edpsil2 = dEdpsil * (-(w_exp / psi_63) *
                           (psi_l / psi_63)**(w_exp - 1) + grl_psir *
                           (w_exp / psi_63) *
                           (psi_r / psi_63)**(w_exp - 1) * grl_psil /
                           (grl_psir + gSR)**2)

    part1 = dAdgs(t, gs, ca, k1_interp, k2_interp, cp_interp,
                  1) * dEdpsil / (a * VPD)
    part2 = - Amax * d2Edpsil2 / (k_max - k_crit) *\
            np.sqrt((k2 + ca) ** 2 * gs ** 2 + 2 * (k2 - ca + 2 * cp) * gs * k1 + k1 ** 2)
    return part2 - part1
Esempio n. 11
0
 def igf(a, x):
     """ Incomplete gamma function """
     return gammainc(a, x) * gammafunc(a)
Esempio n. 12
0
 def cigf(a, x):
     """ Complementary incomplete gamma function """
     return gammaincc(a, x) * gammafunc(a)
Esempio n. 13
0
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
Esempio n. 14
0
    def calculate_P_Wm(self, ppb, sigma_t, b_field=0., n_bunches=None):
        """
        If n_bunches is not specified, ppb has to be either a numpy array with dimensions
        time_steps x n_bunches or n_bunches.
        If n_bunches is specified, ppb can be either a number or an arry with dimensions of timesteps
        sigma_t is either a float or a np array of dimensions time_steps or timp_steps * n_bunches
        Do not specify n_bunches explicitly and implicitly at the same time!
        """

        if n_bunches is None:
            if not hasattr(ppb, '__iter__'):
                raise ValueError('N_bunches has to be specified somehow!')
            else:
                n_bunches = 1.
        else:
            if hasattr(ppb, '__iter__'):
                raise ValueError(
                    'N_bunches should not be specified if a ppb array is provided!'
                )

        rho_B0_T = self.copper_rho_Ohm_m(
            self.temperature_K)  # 0.014 *1e-8 for 20 K

        if not hasattr(b_field, '__iter__') and b_field == 0.:
            rho_B_T = rho_B0_T
        else:
            rho_B0_273 = self.copper_rho_Ohm_m(273.)
            #elias
            rho_B_T = rho_B_T = rho_B0_T * (
                1 + 10**(1.055 * np.log10(b_field *
                                          (rho_B0_273 / rho_B0_T)) - 2.69))

            #philipp
            #try:
            #   rho_B0_4 = self.copper_rho_Ohm_m(4.)
            #except ValueError:
            #    rho_B0_4 = 3.*self.copper_rho_Ohm_m(4.2) - 2.*self.copper_rho_Ohm_m(4.3)
            #rho_B_T = rho_B0_T * (1. + 10.**(-2.69) * (b_field*rho_B0_273/rho_B0_4)**1.055)

            #benoit/nicolas
            #rho_B_T = rho_B0_T *(1.0048 + 0.0038*b_field*self.copper_rho_Ohm_m(300.)/self.copper_rho_Ohm_m(20.))
            #For 20K!!!
            #rho_B_T = 2.4e-10 *(1.0048 + 0.0038*b_field*70.)

        #print rho_B_T
        per_bunch_factor = ppb**2 * sigma_t**(-1.5)

        if hasattr(ppb, '__iter__') and len(ppb.shape) == 2:
            per_bunch_factor = np.sum(per_bunch_factor, axis=1)

        P_no_weld = 1. / self.circumference_m * gammafunc(
            0.75) * n_bunches / self.chamb_radius_m * (
                qe / 2. / np.pi)**2 * np.sqrt(
                    c * rho_B_T * Z0_vac / 2.) * per_bunch_factor

        if self.weld_Thickness_m is not None:
            weld_Factor = 1. + np.sqrt(
                self.weld_Rho_Ohm_m / rho_B_T) * self.weld_Thickness_m / (
                    2. * np.pi * self.chamb_radius_m)
            #weld_Factor = 1.4 # benoit assumption
        else:
            weld_Factor = 1.

        return P_no_weld * weld_Factor