Beispiel #1
0
def calc_stored_energy_abs_incs_fd_peaks_and_indices(forces,
                                                     disps,
                                                     peaks_from='disp'):
    """
    Calculates the absolute change stored energy for an oscillating system

    >>> disp = np.array([0, 4, 0, -2, 0])
    >>> force = np.array([0, 4, 0, -4, 0])
    >>> calc_stored_energy_abs_incs_fd_peaks_and_indices(force, disp)
    (array([ 0.,  8., 12.,  4.]), array([0, 1, 3, 4]))

    Parameters
    ----------
    disps: array_like
        displacement time series
    forces: array_like
        force time series
    peaks_from: str or array_like
        Method to determine peaks or array of peak indices
    :return: array_like
    """
    forces = forces.astype(float)
    disps = disps.astype(float)
    if peaks_from == 'disp':
        peak_indices = eqsig.get_peak_array_indices(disps)
    elif peaks_from == 'cyclic_energy':
        peak_indices = get_energy_peaks_for_cyclic_loading(forces,
                                                           disps)  # slow
    elif not isinstance(peaks_from, str):
        peak_indices = np.array(peaks_from)
    else:
        raise ValueError(
            "'peaks_from' must be either 'disp', 'cyclic_energy' or "
            "array indices, not {0}".format(peaks_from))
    peak_forces = np.take(forces, peak_indices)
    peak_disps = np.take(disps, peak_indices)

    # Take the average of the absolute average and the signed average
    # accounts for sign change through a step
    peak_abs_av_force = average_of_absolute_via_trapz(peak_forces)
    peak_abs_delta_disps = abs(np.diff(peak_disps))
    peak_abs_delta_work = peak_abs_delta_disps * peak_abs_av_force  # trapezoid
    peak_abs_delta_work = np.insert(peak_abs_delta_work, 0, 0)

    return peak_abs_delta_work, peak_indices
Beispiel #2
0
def get_switched_peak_array_indices(values):
    """
    Find the indices for largest peak between each zero crossing

    Parameters
    ----------
    values: array_like

    Returns
    -------
    array_like
    """
    peak_indices = eqsig.get_peak_array_indices(values)
    peak_values = np.take(values, peak_indices)

    last = peak_values[0]
    new_peak_indices = []
    peak_values_set = [0]
    peak_indices_set = [0]
    for i in range(1, len(peak_values)):
        if peak_values[
                i] * last <= 0:  # only add index if sign changes (negative number)
            i_max_set = np.argmax(np.abs(peak_values_set))
            new_peak_indices.append(peak_indices_set[i_max_set])

            last = peak_values[i]
            peak_values_set = []  # reset set
            peak_indices_set = []

        peak_values_set.append(peak_values[i])
        peak_indices_set.append(i)

    if len(peak_values_set):  # add last
        i_max_set = np.argmax(np.abs(peak_values_set))
        new_peak_indices.append(peak_indices_set[i_max_set])
        peak_values_set.append(peak_values[i])
        peak_indices_set.append(i)

    switched_peak_indices = np.take(peak_indices, new_peak_indices)
    return switched_peak_indices
Beispiel #3
0
def fit_3_layer_profile(depths,
                        crr_n15s,
                        fitting_values,
                        crr_non_liq=0.6,
                        max_depth=20):
    """
    Determines the best 3-layer profile fit for a given parameter

    Method uses brut force different CRR values. For each CRR is determines the change points and then evaluates which
    change points are best.

    Sets the caps the other layer crr values to the non liquefying value best to use 0.6 as this is approx the upper
    limit of liquefiable soil. Then the error for over-fitting (defining a non-liq layer as liquefiable) incurs an
    error of 0.6-crr_liq, while under-fitting layers less than or equal to crr_liq incurs the same error
    while layers in between crr_liq and the non-liq limit incur an error proportional to the difference from the defined
    and calculated crr.

    Parameters
    ----------
    depths: array,
        distance from surface
    crr_n15s: array,
        actual values to fit to (note CRR_max=4)
    fitting_values: array,
        possible values of layer 2
    crr_non_liq: float,
        value for layers 1 and 3
    :return:
    """

    if depths[-1] > max_depth:
        indy = np.where(depths > max_depth)[0][0]
    else:
        indy = len(depths)
    std_depths = depths[:indy]
    std_crr_n15s = crr_n15s[:indy]
    n_depths = len(std_depths)
    capped_values = np.clip(std_crr_n15s, None, crr_non_liq)
    diffs = capped_values[:, np.newaxis] - fitting_values[np.newaxis, :]
    cdiffs = np.cumsum(np.abs(diffs), axis=0)

    diffs = []
    h_crusts = []
    h_liqs = []
    for ii in range(len(fitting_values)):
        eline = cdiffs[:, 0] - cdiffs[:, ii]
        peak_ids = eqsig.get_peak_array_indices(eline)
        if eline[peak_ids[1]] > 0:
            peak_ids = peak_ids[:-1]
        else:
            peak_ids = peak_ids[1:-1]
        if len(peak_ids):
            loc_min_is = np.take(peak_ids, np.arange(0, len(peak_ids), 2))
            loc_max_is = np.take(peak_ids, np.arange(1, len(peak_ids), 2))
            loc_mins = np.take(eline, loc_min_is)
            loc_maxs = np.take(eline, loc_max_is)
            opts = loc_mins[np.newaxis, :] - loc_maxs[:, np.newaxis]
            opts *= np.tri(
                *opts.shape
            )  # remove cases where liq layer is higher than crust

            min_i, min_j = np.unravel_index(opts.argmin(), opts.shape)
            i_crust = loc_min_is[min_j]
            i_liq = loc_max_is[min_i]
            h_crusts.append(depths[i_crust + 1])
            h_liqs.append(depths[i_liq + 1] - depths[i_crust + 1])

            refined_errors = cdiffs[i_crust][0] + (
                cdiffs[i_liq][ii] - cdiffs[i_crust][ii]) + (cdiffs[-1][0] -
                                                            cdiffs[i_liq][0])
            diffs.append(refined_errors)
        else:
            h_crusts.append(depths[-1])
            h_liqs.append(0)
            diffs.append(1e6)

    i_best = np.argmin(diffs)

    h_crust = h_crusts[i_best]
    h_liq = h_liqs[i_best]
    p_value = fitting_values[i_best]
    diff = diffs[i_best]
    normed_diff = diff / (n_depths * crr_non_liq)

    return h_crust, h_liq, p_value, normed_diff
Beispiel #4
0
def fit_n_layer_profile(depths,
                        crr_n15s,
                        n=3,
                        crr_n15_opts=None,
                        cap=0.6,
                        max_depth=20):
    """
    Determines the best n-layer profile fit for a given parameter

    Method:
    1) Computes the cumulative absolute difference between the upper bound and the actual values
    2) Cycles through a range of guess values (between upper and lower bounds), computes the cumulative absolute
       difference between a guessed value and the actual values
    3) For each guess it determines the change points
    4) For each guess, Evaluates which change points pairs are best (either 1 or 2 depending on n).
    5) For each guess, for each change point pair, compute mean of values between pair (least error)
    6) For each guess, compute the total error as the sum of the error from all of the non-fitted and fitted layers
    7) Select guess which has the least error

    Parameters
    ----------
    depths: array
        Distance from surface
    crr_n15s: array
        Actual values to fit to
    n: int (3 or 5)
        Number of layers to fit
    crr_n15_opts: array_like
        Possibly options for CRR_n15
    max_depth: float
        Maximum distance to consider in fitting
    cap: float
        Clips all actual values to this maximum prior to fitting

    Returns
    -------
    array_like: depths to top of liq layers
    array_like: depths to top of non-liq layers
    array_like: fitted values in liq layers
    float: normalised error
    """
    if not (n == 3 or n == 5):
        raise ValueError("n must be either 3 or 5")
    n_liqs = int((n - 1) / 2)

    # prepare search array
    if crr_n15_opts is None:
        if n_liqs == 1:
            crr_n15_opts = np.array([0.6, 0.5, 0.2, 0.06])
            # q_c1n_cs = np.arange(0, 180., 5.)
            # crr_n15_opts = bi_functions.calc_crr_m7p5_from_qc1ncs(q_c1n_cs)[::-1]
        else:
            q_c1n_cs = np.arange(0, 180., 5.)
            crr_n15_opts = bi_functions.calc_crr_m7p5_from_qc1ncs(
                q_c1n_cs)[::-1]

    # standardise depth
    if depths[-1] > max_depth:
        indy = np.where(depths > max_depth)[0][0]
    else:
        indy = len(depths)
    std_depths = depths[:indy]
    std_crr_n15s = crr_n15s[:indy]
    n_depths = len(std_depths)

    # enforce cap
    std_crr_n15s = np.clip(std_crr_n15s, None, cap)

    # compute difference between options and actual values
    init_diffs = std_crr_n15s[:, np.newaxis] - crr_n15_opts[np.newaxis, :]
    init_cdiffs = np.cumsum(np.abs(init_diffs), axis=0)

    # prepare output arrays
    normed_diffs = []
    d_liqs = [[] for i in range(n_liqs)]
    d_nonliqs = [[] for i in range(n_liqs)]
    crrs = [[] for i in range(n_liqs)]

    # evaluate each option
    for ii in range(len(crr_n15_opts)):
        opts_lay = []
        eline = init_cdiffs[:, 0] - init_cdiffs[:, ii]
        peak_ids = eqsig.get_peak_array_indices(eline) + 1

        if len(peak_ids) > 4 or (len(peak_ids) > 2 and n_liqs == 1):
            # continue
            if eline[peak_ids[1]] > 0:
                peak_ids = peak_ids[:-1]
            else:
                peak_ids = peak_ids[1:-1]

            poss_i_tops = np.take(peak_ids, np.arange(0, len(peak_ids), 2))
            poss_i_bots = np.take(peak_ids, np.arange(1, len(peak_ids), 2))
            poss_i_tops = np.insert(poss_i_tops, len(poss_i_tops),
                                    len(std_crr_n15s) - 1)  # add end
            poss_i_bots = np.insert(poss_i_bots, len(poss_i_bots),
                                    len(std_crr_n15s) - 1)
            poss_err_tops = np.take(eline, poss_i_tops)
            poss_err_bots = np.take(eline, poss_i_bots)
            for ll in range(n_liqs):
                if len(poss_i_tops) < n_liqs or len(poss_i_bots) < n_liqs:
                    opts_lay.append([0])
                else:
                    # error occurred for each change point pair
                    opts_lay.append(poss_err_tops[np.newaxis, ll:] -
                                    poss_err_bots[ll:, np.newaxis])
                    # remove cases where i_bot is higher than i_top
                    opts_lay[ll] *= np.tri(*opts_lay[ll].shape)
            if n_liqs == 1:
                opts_l1f = opts_lay[0]
                j, i = np.unravel_index(opts_l1f.argmin(), opts_l1f.shape)
                i_tops = [int(poss_i_tops[i])]
                i_bots = [int(poss_i_bots[j])]

            elif n_liqs == 2:
                opts_l1f = opts_lay[0].flatten()
                top1_is = poss_i_tops[np.newaxis, :] * np.ones_like(
                    opts_lay[0], dtype=int)
                bot1_is = poss_i_bots[:, np.newaxis] * np.ones_like(
                    opts_lay[0], dtype=int)

                opts_l2f = opts_lay[1].flatten()
                top2_is = poss_i_tops[np.newaxis, 1:] * np.ones_like(
                    opts_lay[1], dtype=int)
                bot2_is = poss_i_bots[1:, np.newaxis] * np.ones_like(
                    opts_lay[1], dtype=int)

                opts = opts_l1f[np.newaxis, :] + opts_l2f[:, np.newaxis]
                top1_is = top1_is.flatten()[np.newaxis, :] * np.ones_like(
                    opts, dtype=int)
                bot1_is = bot1_is.flatten()[np.newaxis, :] * np.ones_like(
                    opts, dtype=int)

                top2_is = top2_is.flatten()[:, np.newaxis] * np.ones_like(
                    opts, dtype=int)
                bot2_is = bot2_is.flatten()[:, np.newaxis] * np.ones_like(
                    opts, dtype=int)

                # remove cases where i_crust_l2 < i_liq_l1
                opts = np.where(top2_is < bot1_is, 1e10, opts)
                # remove cases where i_crust_l2 > i_liq_l2
                opts = np.where(top2_is > bot2_is, 1e10, opts)
                opts = np.where(top2_is == len(std_depths) - 1, 1e10, opts)

                lay1_i, lay2_i = np.unravel_index(opts.argmin(), opts.shape)
                i_tops = [
                    int(top1_is[lay1_i][lay2_i]),
                    int(top2_is[lay1_i][lay2_i])
                ]
                i_bots = [
                    int(bot1_is[lay1_i][lay2_i]),
                    int(bot2_is[lay1_i][lay2_i])
                ]

            else:
                raise ValueError("n_liqs must be either 1 or 2")

            # total_err = init_cdiffs[i_tops[0]][0]
            crr_profile = np.ones_like(std_crr_n15s) * cap
            for ll in range(n_liqs):
                d_liqs[ll].append(depths[i_tops[ll]])
                d_nonliqs[ll].append(depths[i_bots[ll]])
                if i_tops[ll] == i_bots[ll]:
                    crrs[ll].append(cap)
                    # err = 0
                else:
                    # Median equal to min of absolute deviation
                    crr_median = np.median(std_crr_n15s[i_tops[ll]:i_bots[ll]])
                    crrs[ll].append(crr_median)
                    crr_profile[i_tops[ll]:i_bots[ll]] = crr_median
                # err = np.sum(np.abs(capped_values[i_tops[ll]:i_bots[ll]] - crrs[ll][ii]))
                # total_err += err
            total_err = np.sum(abs(std_crr_n15s - crr_profile))

            normed_diffs.append(total_err / (n_depths * cap))

        else:
            if len(peak_ids) <= 2:
                for ll in range(n_liqs):
                    d_liqs[ll].append(0)
                    d_nonliqs[ll].append(depths[-1])
                    crrs[ll].append(cap)
                normed_diffs.append(1e6)
            else:
                d_liqs[0].append(depths[peak_ids[1]])
                d_nonliqs[0].append(depths[peak_ids[2]])
                crr_median = np.median(std_crr_n15s[peak_ids[1]:peak_ids[2]])
                crrs[0].append(crr_median)
                d_liqs[1].append(depths[-1])
                d_nonliqs[1].append(depths[-1])
                crrs[1].append(cap)
                crr_profile = np.ones_like(std_crr_n15s) * cap
                crr_profile[peak_ids[1]:peak_ids[2]] = crr_median
                total_err = np.sum(abs(std_crr_n15s - crr_profile))
                normed_diffs.append(total_err / (n_depths * cap))

    normed_diffs = np.array(normed_diffs)
    d_liqs = np.array(d_liqs)
    d_nonliqs = np.array(d_nonliqs)
    crrs = np.array(crrs)

    i_best = np.argmin(normed_diffs)
    normed_diff = normed_diffs[i_best]

    # change to ECP logic of depths to top of layers
    d_liqs = d_liqs[:, i_best]
    d_nonliqs = d_nonliqs[:, i_best]

    return d_liqs, d_nonliqs, crrs[:, i_best], normed_diff
Beispiel #5
0
                                                         g_mod_ref=sl.g_mod / 1e3,
                                                         bulk_mod_ref=sl.bulk_mod / 1e3,
                                                         peak_strain=0.05,
                                                         cohesion=sl.cohesion / 1e3,
                                                         phi=sl.phi,
                                                         p_ref=vert_sig_eff,
                                                         d=0.0,
                                                         n_surf=20
                                                         )

    disps = np.array([0.0, 0.00003, -0.00003, 0.0004, 0.0001, 0.0009, -0.0012]) * 10
    disps = np.array([0.0, 0.001, 0.0002])
    disps = np.linspace(0.0, 0.01, 100)
    stress, strain, v_eff, h_eff, exit_code = run_2d_strain_driver(osi, base_mat, esig_v0=vert_sig_eff, disps=disps,
                                                                   handle='warn', verbose=1)
    print(exit_code)
    pis = eqsig.get_peak_array_indices(stress)
    n_cycs = 0.5 * np.arange(len(pis)) - 0.25
    n_cycs[0] = 0
    n_cycles = np.interp(np.arange(len(stress)), pis, n_cycs)
    bf, sps = plt.subplots(nrows=2)
    sps[0].plot(strain, stress)
    sps[0].plot(strain[pis], stress[pis], 'o')
    sps[0].axhline(sl.cohesion / 1e3, c='k')
    sps[1].plot(stress)
    sps[1].plot(v_eff)
    sps[1].plot(h_eff)

    plt.show()