Ejemplo n.º 1
0
def write_intxt(input_object, output_file, label=None):
    ofile = open(output_file, 'w');
    if label:
        ofile.write(label);
    ofile.write("# General: poissons_ratio friction_coef lon_min lon_max lon_zero lat_min lat_max lat_zero\n");
    ofile.write("# Source_Patch: strike rake dip length_km width_km lon lat depth_km slip_m\n");
    ofile.write("# Receiver: strike rake dip length_km width_km lon lat depth_km\n\n");
    ofile.write("General: %f %f %f %f %f %f %f %f \n" % (input_object.PR1, input_object.FRIC, input_object.minlon,
                                                         input_object.maxlon, input_object.zerolon, input_object.minlat,
                                                         input_object.maxlat, input_object.zerolat) );
    for src in input_object.source_object:
        if not src.potency:  # write a finite source
            L = fault_vector_functions.get_strike_length(src.xstart, src.xfinish, src.ystart, src.yfinish);  # in km
            W = fault_vector_functions.get_downdip_width(src.top, src.bottom, src.dipangle);  # in km
            fault_lon, fault_lat = fault_vector_functions.xy2lonlat(src.xstart, src.ystart, src.zerolon, src.zerolat);
            slip = fault_vector_functions.get_vector_magnitude([src.rtlat, src.reverse]);  # in m
            ofile.write("Source_Patch: %f %f %f %f %f %f %f %f %f\n" % (src.strike, src.rake, src.dipangle, L, W,
                                                                        fault_lon, fault_lat, src.top, slip));
        if src.potency:   # write a focal mechanism source
            continue;   # still working on this.
    for rec in input_object.receiver_object:
        L = fault_vector_functions.get_strike_length(rec.xstart, rec.xfinish, rec.ystart, rec.yfinish);  # in km
        W = fault_vector_functions.get_downdip_width(rec.top, rec.bottom, rec.dipangle);  # in km
        fault_lon, fault_lat = fault_vector_functions.xy2lonlat(rec.xstart, rec.ystart, rec.zerolon, rec.zerolat);
        ofile.write("Receiver: %f %f %f %f %f %f %f %f \n" % (rec.strike, rec.rake, rec.dipangle, L, W, fault_lon,
                                                              fault_lat, rec.top) );
    ofile.close();
    print("Writing file %s " % output_file);
    return;
Ejemplo n.º 2
0
def read_stat2C_geometry(infile):
    """
    Reading a fault geometry file used for stat2c.f, specifically for the Cascadia subduction zone.
    Returns a list of fault dictionaries in the internal format.
    """
    faultlist = []
    with open(infile, 'r') as ifile:
        for line in ifile:
            temp = line.split()
            if len(temp) == 2:
                upper_depth, lower_depth = float(temp[0]), float(temp[1])
            elif len(temp) == 7:
                lower_lat_corner = float(temp[0])
                # in degrees
                lower_lon_corner = float(temp[1])
                # in degrees
                length = float(temp[2])
                # in km
                strike = float(temp[3])
                # in degrees
                rake = float(temp[4])
                # in degrees
                dip = float(temp[6])
                # in degrees
                slip = float(temp[5]) / 100
                # from cm/yr into m/yr
                downdip_width = fault_vector_functions.get_downdip_width(
                    upper_depth, lower_depth, dip)

                vector_mag = downdip_width * np.cos(np.deg2rad(dip))
                # how far the bottom edge is displaced
                upper_corner_along_strike = fault_vector_functions.add_vector_to_point(
                    0, 0, vector_mag, strike - 90)
                upper_corner_back_edge = fault_vector_functions.add_vector_to_point(
                    upper_corner_along_strike[0], upper_corner_along_strike[1],
                    length, strike + 180)
                fault_lon, fault_lat = fault_vector_functions.xy2lonlat_single(
                    upper_corner_back_edge[0], upper_corner_back_edge[1],
                    lower_lon_corner, lower_lat_corner)

                new_fault = {
                    "strike": strike,
                    "dip": dip,
                    "length": length,
                    "rake": rake,
                    "slip": slip,
                    "tensile": 0,
                    "depth": upper_depth,
                    "width": downdip_width,
                    "lon": fault_lon,
                    "lat": fault_lat
                }
                faultlist.append(new_fault)

    return faultlist
Ejemplo n.º 3
0
def compute_strains_stresses_from_one_fault(source, x, y, z, alpha):
    """
    The main math of DC3D
    Operates on a source object (e.g., fault),
    and an xyz position in the same cartesian reference frame.
    """
    L = fault_vector_functions.get_strike_length(source.xstart, source.xfinish,
                                                 source.ystart, source.yfinish)
    W = fault_vector_functions.get_downdip_width(source.top, source.bottom,
                                                 source.dipangle)
    depth = source.top
    dip = source.dipangle
    strike_slip = source.rtlat * -1
    # The dc3d coordinate system has left-lateral positive.
    dip_slip = source.reverse

    # Preparing to rotate to a fault-oriented coordinate system.
    theta = source.strike - 90
    theta = np.deg2rad(theta)
    R = np.array([[np.cos(theta), -np.sin(theta), 0],
                  [np.sin(theta), np.cos(theta), 0], [0, 0, 1]])
    # horizontal rotation into strike-aligned coordinates.
    R2 = np.array([[np.cos(-theta), -np.sin(-theta), 0],
                   [np.sin(-theta), np.cos(-theta), 0], [0, 0, 1]])

    # Compute the position relative to the translated, rotated fault.
    translated_pos = np.array([[x - source.xstart], [y - source.ystart], [-z]])
    xyz = R.dot(translated_pos)
    if source.potency:
        success, u, grad_u = dc3d0wrapper(
            alpha, [xyz[0], xyz[1], xyz[2]], depth, dip, [
                source.potency[0], source.potency[1], source.potency[2],
                source.potency[3]
            ])
        grad_u = grad_u * 1e-9
        # DC3D0 Unit correction: potency from N-m results in strain in nanostrain
        u = u * 1e-6
        # Unit correction: potency from N-m results in displacements in microns.
    else:
        success, u, grad_u = dc3dwrapper(
            alpha, [xyz[0], xyz[1], xyz[2]], depth, dip, [0, L], [-W, 0],
            [strike_slip, dip_slip, source.tensile])
        grad_u = grad_u * 1e-3
        # DC3D Unit correction.
    # Solve for displacement gradients at certain xyz position

    # Rotate grad_u back into the unprimed coordinates.
    desired_coords_grad_u = np.dot(R2, np.dot(grad_u, R2.T))
    desired_coords_u = R2.dot(np.array([[u[0]], [u[1]], [u[2]]]))

    return desired_coords_grad_u, desired_coords_u
Ejemplo n.º 4
0
def get_fault_four_corners(fault_object, coords="cartesian"):
    """
    Get the four corners of the object, including updip and downdip.
    depth is fault_object.top
    dip is fault_object.dipangle (in case you need it)
    coords can be "cartesian" or "geographic" for lon/lat
    """
    W = fault_vector_functions.get_downdip_width(fault_object.top,
                                                 fault_object.bottom,
                                                 fault_object.dipangle)
    strike = fault_object.strike

    updip_point0 = [fault_object.xstart, fault_object.ystart]
    updip_point1 = [fault_object.xfinish, fault_object.yfinish]
    vector_mag = W * np.cos(np.deg2rad(fault_object.dipangle))
    # how far the bottom edge is displaced
    # downdip from map-view
    downdip_point0 = fault_vector_functions.add_vector_to_point(
        fault_object.xstart, fault_object.ystart, vector_mag, strike + 90)
    # strike+90 = downdip direction.
    downdip_point1 = fault_vector_functions.add_vector_to_point(
        fault_object.xfinish, fault_object.yfinish, vector_mag, strike + 90)

    if coords == 'geographic':
        updip_point0 = fault_vector_functions.xy2lonlat_single(
            updip_point0[0], updip_point0[1], fault_object.zerolon,
            fault_object.zerolat)
        updip_point1 = fault_vector_functions.xy2lonlat_single(
            updip_point1[0], updip_point1[1], fault_object.zerolon,
            fault_object.zerolat)
        downdip_point0 = fault_vector_functions.xy2lonlat_single(
            downdip_point0[0], downdip_point0[1], fault_object.zerolon,
            fault_object.zerolat)
        downdip_point1 = fault_vector_functions.xy2lonlat_single(
            downdip_point1[0], downdip_point1[1], fault_object.zerolon,
            fault_object.zerolat)

    x_total = [
        updip_point0[0], updip_point1[0], downdip_point1[0], downdip_point0[0],
        updip_point0[0]
    ]
    y_total = [
        updip_point0[1], updip_point1[1], downdip_point1[1], downdip_point0[1],
        updip_point0[1]
    ]
    x_updip = [updip_point0[0], updip_point1[0]]
    y_updip = [updip_point0[1], updip_point1[1]]

    return [x_total, y_total, x_updip, y_updip]
Ejemplo n.º 5
0
def get_fault_center(fault_object):
    """
    Compute the x-y-z coordinates of the center of a PyCoulomb fault patch (a namedtuple)
    """
    W = fault_vector_functions.get_downdip_width(fault_object.top,
                                                 fault_object.bottom,
                                                 fault_object.dipangle)
    center_z = (fault_object.top + fault_object.bottom) / 2.0
    updip_center_x = (fault_object.xstart + fault_object.xfinish) / 2.0
    updip_center_y = (fault_object.ystart + fault_object.yfinish) / 2.0
    vector_mag = W * np.cos(np.deg2rad(fault_object.dipangle)) / 2.0
    # how far the middle is displaced
    # downdip from map-view
    center_point = fault_vector_functions.add_vector_to_point(
        updip_center_x, updip_center_y, vector_mag, fault_object.strike + 90)
    # strike+90 = downdip direction.
    center = [center_point[0], center_point[1], center_z]
    return center
Ejemplo n.º 6
0
def read_fault_slip_line_static1d_visco1d(line, upper_depth, lower_depth, dip):
    """
    read a line from fred's format of faults into my format of faults
    for Visco1D, the slip field is pretty meaningless
    """
    lower_lat_corner = float(line.split()[0])
    # in degrees
    lower_lon_corner = float(line.split()[1])
    # in degrees
    length = float(line.split()[2])
    # in km
    strike = float(line.split()[3])
    # in degrees
    rake = float(line.split()[4])
    # in degrees
    slip = float(line.split()[5])
    # in cm
    downdip_width = fault_vector_functions.get_downdip_width(
        upper_depth, lower_depth, dip)
    vector_mag = downdip_width * np.cos(np.deg2rad(dip))
    # how far bottom edge is displaced from top edge
    upper_corner_along_strike = fault_vector_functions.add_vector_to_point(
        0, 0, vector_mag, strike - 90)
    upper_corner_back_edge = fault_vector_functions.add_vector_to_point(
        upper_corner_along_strike[0], upper_corner_along_strike[1], length,
        strike + 180)
    fault_lon, fault_lat = fault_vector_functions.xy2lonlat_single(
        upper_corner_back_edge[0], upper_corner_back_edge[1], lower_lon_corner,
        lower_lat_corner)
    new_fault = {
        "strike": strike,
        "dip": dip,
        "length": length,
        "rake": rake,
        "slip": slip / 100,
        "tensile": 0,
        "depth": upper_depth,
        "width": downdip_width,
        "lon": fault_lon,
        "lat": fault_lat
    }
    return new_fault
Ejemplo n.º 7
0
def convert_2d_segments_to_internal_fault_dictionary(fault_segments, dip, dip_direction, top_depth, bottom_depth,
                                                     slip_cm, rake):
    """
    fault_segment includes: (starting lon, starting_lat, strike, length, ending_lon, ending_lat)
    where starting_lon is probably south of ending_lon.
    We are converting to the internal fault_dictionary format from Elastic_stresses_py
    """
    fault_dict_list = [];
    for item in fault_segments:
        # Flip strike/dip if necessary
        if dip_direction == 'south':
            strike = item[2] - 180;
            # Do I flip the lon/lat to the other corner here too?  Not totally sure.  Should test this.
        else:
            strike = item[2];
        downdip_width = fault_vector_functions.get_downdip_width(top_depth, bottom_depth, dip);
        new_fault = {"strike": strike, "dip": dip, "length": item[3], "rake": rake, "slip": slip_cm / 100,
                     "tensile": 0, "depth": top_depth, "width": downdip_width, "lon": item[0], "lat": item[1]};
        fault_dict_list.append(new_fault);
    return fault_dict_list;
Ejemplo n.º 8
0
def get_fault_slip_moment(fault_object, mu):
    """
    From a source fault object, calculate the seismic moment.
    Must be a finite fault, not a point source.
    Not really used yet, but could be useful in the future.
    """
    if fault_object.potency:  # for the case of point source, we can't do the moment calculation
        return None, None
    W = fault_vector_functions.get_downdip_width(fault_object.top,
                                                 fault_object.bottom,
                                                 fault_object.dipangle)
    L = fault_vector_functions.get_strike_length(fault_object.xstart,
                                                 fault_object.xfinish,
                                                 fault_object.ystart,
                                                 fault_object.yfinish)
    area = L * W * 1000 * 1000
    slip = fault_vector_functions.get_vector_magnitude(
        [fault_object.rtlat, fault_object.reverse])
    seismic_moment = mu * area * slip
    moment_magnitude = moment_calculations.mw_from_moment(seismic_moment)
    return seismic_moment, moment_magnitude
Ejemplo n.º 9
0
def coulomb_fault_to_fault_dict(source_object):
    """Convert a list of fault objects from Elastic_stresses_py into a list of internal dictionary objects"""
    fault_dict_list = []
    for src in source_object:
        if src.potency:
            print(
                "ERROR! Cannot convert a point source into a rectangular source. Skipping..."
            )
            continue
        one_fault = {
            "strike":
            src.strike,
            "dip":
            src.dipangle,
            "depth":
            src.top,
            "rake":
            fault_vector_functions.get_rake(rtlat_strike_slip=src.rtlat,
                                            dip_slip=src.reverse),
            "slip":
            fault_vector_functions.get_total_slip(src.rtlat, src.reverse),
            "tensile":
            src.tensile,
            "length":
            fault_vector_functions.get_strike_length(src.xstart, src.xfinish,
                                                     src.ystart, src.yfinish),
            "width":
            fault_vector_functions.get_downdip_width(src.top, src.bottom,
                                                     src.dipangle)
        }
        lon, lat = fault_vector_functions.xy2lonlat(src.xstart, src.ystart,
                                                    src.zerolon, src.zerolat)
        one_fault["lon"] = lon
        one_fault["lat"] = lat
        fault_dict_list.append(one_fault)
    return fault_dict_list
Ejemplo n.º 10
0
def split_subfault_receivers(params, inputs):
    strike_split = params.strike_num_receivers
    dip_split = params.dip_num_receivers

    if strike_split == 1 and dip_split == 1:
        # If we're not splitting the subfaults...
        subfaulted_receivers = inputs.receiver_object
        print("Not subdividing receiver faults further.")
    else:
        subfaulted_receivers = []
        print("Splitting %d receiver faults into %d subfaults each." %
              (len(inputs.receiver_object), strike_split * dip_split))

        for fault in inputs.receiver_object:  # for each receiver...
            # We find the depths corresponding to the tops and bottoms of our new sub-faults
            zsplit_array = get_split_z_array(fault.top, fault.bottom,
                                             dip_split)

            for j in range(dip_split):  # First we split it up by dip.
                # Get the new coordinates of the top of the fault plane.
                W = fault_vector_functions.get_downdip_width(
                    fault.top, zsplit_array[j], fault.dipangle)
                vector_mag = W * np.cos(np.deg2rad(fault.dipangle))
                # how far the bottom edge is displaced downdip from map-view

                # Get the starting points for the next row of fault subpatches.
                [start_x_top,
                 start_y_top] = fault_vector_functions.add_vector_to_point(
                     fault.xstart, fault.ystart, vector_mag, fault.strike + 90)
                [finish_x_top,
                 finish_y_top] = fault_vector_functions.add_vector_to_point(
                     fault.xfinish, fault.yfinish, vector_mag,
                     fault.strike + 90)

                [xsplit_array, ysplit_array
                 ] = get_split_x_y_arrays(start_x_top, finish_x_top,
                                          start_y_top, finish_y_top,
                                          strike_split)

                for k in range(strike_split):
                    single_subfaulted_receiver = cc.Faults_object(
                        xstart=xsplit_array[k],
                        xfinish=xsplit_array[k + 1],
                        ystart=ysplit_array[k],
                        yfinish=ysplit_array[k + 1],
                        Kode=fault.Kode,
                        rtlat=0,
                        reverse=0,
                        tensile=0,
                        potency=[],
                        strike=fault.strike,
                        dipangle=fault.dipangle,
                        zerolon=inputs.zerolon,
                        zerolat=inputs.zerolat,
                        rake=fault.rake,
                        top=zsplit_array[j],
                        bottom=zsplit_array[j + 1],
                        comment=fault.comment)
                    subfaulted_receivers.append(single_subfaulted_receiver)

    subfaulted_objects = cc.Input_object(
        PR1=inputs.PR1,
        FRIC=inputs.FRIC,
        depth=inputs.depth,
        start_gridx=inputs.start_gridx,
        finish_gridx=inputs.finish_gridx,
        start_gridy=inputs.start_gridy,
        finish_gridy=inputs.finish_gridy,
        xinc=inputs.xinc,
        yinc=inputs.yinc,
        minlon=inputs.minlon,
        maxlon=inputs.maxlon,
        zerolon=inputs.zerolon,
        minlat=inputs.minlat,
        maxlat=inputs.maxlat,
        zerolat=inputs.zerolat,
        source_object=inputs.source_object,
        receiver_object=subfaulted_receivers,
        receiver_horiz_profile=inputs.receiver_horiz_profile)

    return subfaulted_objects
Ejemplo n.º 11
0
def read_four_corners_fault_file(filename):
    """
    Read fault file from Shengji Wei, EPSL, 2015.
    Provided: lat/lon/depth of each corner.
    Read into an internal fault dictionary
    """
    print("Reading file %s" % filename);
    lons, lats, depths = [], [], [];
    ifile = open(filename, 'r');
    for line in ifile:
        temp = line.split();
        if len(temp) == 0:
            continue;
        if temp[0][0] == "#":
            continue;
        else:
            lons.append(float(temp[0]))
            lats.append(float(temp[1]))
            depths.append(float(temp[2]))
    ifile.close();

    # Get parameters of fault patch; assuming four vertices are given, and top depth is same between two top vertices.
    x, y = fault_vector_functions.latlon2xy(lons, lats, lons[0], lats[0]);

    # Find the top of the fault plane
    shallow_depth = np.min(depths);
    deep_depth = np.max(depths);
    shallow_depth_idx = np.where(depths == shallow_depth)
    idx0 = shallow_depth_idx[0][0];
    idx1 = shallow_depth_idx[0][1];

    deltax = x[idx1] - x[idx0];
    deltay = y[idx1] - y[idx0];
    strike_initial = fault_vector_functions.get_strike(deltax, deltay)  # STRIKE MIGHT BE 180 DEGREES AWAY
    dip = fault_vector_functions.get_dip_degrees(x[-2], y[-2], depths[-2], x[-1], y[-1], depths[-1]);
    # Assuming the last two entries go from the bottom to the top.

    # MIGHT REVERSE THE STRIKE HERE.
    strike_vector = fault_vector_functions.get_strike_vector(strike_initial);
    dip_vector = fault_vector_functions.get_dip_vector(strike_initial, dip);
    xp = np.cross(dip_vector, strike_vector);  # dip x strike for outward facing normal, by right hand rule.
    if xp[2] < 0:
        print("WARNING: STRIKE AND DIP DON'T OBEY RIGHT HAND RULE. FLIPPING STRIKE.");
        strike = strike_initial+180;
    else:
        strike = strike_initial;
    if strike > 360:
        strike = strike-360;

    length = fault_vector_functions.get_strike_length(x[idx0], x[idx1], y[idx0], y[idx1]);
    width = fault_vector_functions.get_downdip_width(shallow_depth, deep_depth, dip);

    # GET THE TOP CORNER OF THE FAULT PLANE (ONE OF TWO OPTIONS)
    print("  ", strike, "degrees strike");
    print("  ", dip, "degrees dip");
    print("  ", length, "km length");
    print("  ", width, "km width");

    if strike_initial == strike:
        updip_corner_lon = lons[idx0];
        updip_corner_lat = lats[idx0];
        updip_corner_depth = depths[idx0];
    else:
        updip_corner_lon = lons[idx1];
        updip_corner_lat = lats[idx1];
        updip_corner_depth = depths[idx1];

    fault_object = {'strike': strike, 'slip': 0, 'tensile': 0, 'rake': 0, 'length': length, 'width': width, 'dip': dip,
                    'lon': updip_corner_lon, 'lat': updip_corner_lat, 'depth': updip_corner_depth};
    return fault_object;